######################################################################
#
#  RADIUS over TLS (radsec)
#
#  When a new client connects, the various TLS parameters for the
#  connection are available as dynamic expansions, e.g.
#
#       %{listen:TLS-Client-Cert-Common-Name}
#
#  Along with other TLS-Client-Cert-... attributes.
#  These expansions will only exist if the relevant fields
#  are in the client certificate.  Read the debug output to see
#  which fields are available.  Look for output like the following:
#
# (0) TLS - Creating attributes from certificate OIDs
# (0)   TLS-Client-Cert-Subject-Alt-Name-Dns := "one.example.org"
# (0)   TLS-Client-Cert-Subject-Alt-Name-Dns := "two.example.org"
# ...
#
#  It is also possible to distinguish between connections which have
#  TLS enables, and ones which do not.  The expansion:
#
#       %{listen:tls}
#
#  Will return "yes" if the connection has TLS enabled.  It will
#  return "no" if TLS is not enabled for a particular listen section.
#
#  A number of TLS-Client-Cert-.. attributes holds X509v3 extensions
#  data, attributes named the way OpenSSL names them. It is possible
#  to extract data for an extension not known to OpenSSL by defining
#  a custom string attribute which contains extension OID in it's
#  name after 'TLS-Client-Cert-' prefix. E.g.:
#
#  ATTRIBUTE    TLS-Client-Cert-1.3.6.1.4.1.311.21.7    3002    string
#
#  which will yield something simmilar to:
#
#   (0) eap_tls: TLS - Creating attributes from certificate OIDs
#   (0) eap_tls:   TLS-Client-Cert-1.3.6.1.4.1.311.21.7 += "0x302e06"
#   ...
#
######################################################################

listen {

		# ipaddr = $ENV{FREERADIUS_SITES_TLS_LISTEN}
		ipaddr = *
		port = $ENV{FREERADIUS_SITES_TLS_PORT}

		#
		#  TCP and TLS sockets can accept Access-Request and Accounting-Request on the same socket.
		#
		#       auth      = only Access-Request
		#       acct      = only Accounting-Request
		#       auth+acct = both
		#       coa       = only CoA / Disconnect requests
		#
		type = auth+acct

		# For now, only TCP transport is allowed.
		proto = tcp

		# Send packets to the default virtual server
		virtual_server = default

		clients = radsec

		#  Use the haproxy "PROXY protocol".
		#
		#  This configuration allows for many FreeRADIUS servers to be behind a haproxy server.  The "PROXY protocol" allows haproxy to send the actual client IP to FreeRADIUS.
		#
		#  This will work ONLY for RadSec (TLS).  Both the haproxy AND the RadSec client MUST be listed as allowed RADIUS clients.
		#
		#  haproxy needs to have "send-proxy" configured for this server. Health checks should be turned off, as haproxy does not support RADIUS health checks.
		#
		#  The main use of this feature is for scalability. There is no longer any need to have a RADIUS proxy as a load balancer.
		#  haproxy is fast, stable, and supports dynamic reloads!
		#
		#  The only problem is that many RADIUS clients do not support RadSec.  That situation will hopefully change over time.
		#
#       proxy_protocol = no

		#  When this is set to "yes", new TLS connections are processed through a section called
		#
		#       Autz-Type New-TLS-Connection {
		#                 ...
		#       }
		#
		#  The request contains TLS client certificate attributes,
		#  and nothing else.  The debug output will print which
		#  attributes are available on your system.
		#
		#  If the section returns "ok" or "updated", then the
		#  connection is accepted.  Otherwise the connection is
		#  terminated.
		#
#       check_client_connections = yes

		#
		#  Connection limiting for sockets with "proto = tcp".
		#
		limit {
			  #  Limit the number of simultaneous TCP connections to the socket
			  #
			  #  The default is 16.
			  #  Setting this to 0 means "no limit"
			  max_connections = 16

			  #  The per-socket "max_requests" option does not exist.

			  #  The lifetime, in seconds, of a TCP connection.  After this lifetime, the connection will be closed.
			  #
			  #  Setting this to 0 means "forever".
			  lifetime = 0

			  #  The idle timeout, in seconds, of a TCP connection. If no packets have been received over the connection for this time, the connection will be closed.
			  #
			  #  Setting this to 0 means "no timeout".
			  #  We STRONGLY RECOMMEND that you set an idle timeout.
			  #
			  idle_timeout = 30
		}

		#  This is *exactly* the same configuration as used by the EAP-TLS
		#  module.  It's OK for testing, but for production use it's a good
		#  idea to use different server certificates for EAP and for RADIUS
		#  transport.
		#
		#  If you want only one TLS configuration for multiple sockets,
		#  then we suggest putting "tls { ...}" into radiusd.conf.
		#  The subsection below can then be changed into a reference:
		#
		#       tls = ${tls}
		#
		#  Which means "the tls sub-section is not here, but instead is in
		#  the top-level section called 'tls'".
		#
		#  If you have multiple tls configurations, you can put them into
		#  sub-sections of a top-level "tls" section.  There's no need to
		#  call them all "tls".  You can then use:
		#
		#       tls = ${tls.site1}
		#
		#  to refer to the "site1" sub-section of the "tls" section.
		#
		tls {
				private_key_password = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_PASSWORD}
				private_key_file = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_FILE}

				# Accept an expired Certificate Revocation List
		#       allow_expired_crl = no

				#  If Private key & Certificate are located in
				#  the same file, then private_key_file &
				#  certificate_file must contain the same file
				#  name.
				#
				#  If ca_file (below) is not used, then the
				#  certificate_file below MUST include not
				#  only the server certificate, but ALSO all
				#  of the CA certificates used to sign the
				#  server certificate.
				certificate_file = $ENV{FREERADIUS_SITES_TLS_CERTIFICATE_FILE}


				#  Trusted Root CA list
				#
				#  ALL of the CA's in this list will be trusted to issue client certificates for authentication.
				#
				#  In general, you should use self-signed certificates for 802.1x (EAP) authentication.
				#  In that case, this CA file should contain *one* CA certificate.
				#
				#  This parameter is used only for EAP-TLS, when you issue client certificates.  If you do not use client certificates, and you do not want
				#  to permit EAP-TLS authentication, then delete this configuration item.
				ca_file = $ENV{FREERADIUS_SITES_TLS_CA_FILE}

				#  For DH cipher suites to work, you have to run OpenSSL to create the DH file first:
				#
				#       openssl dhparam -out certs/dh 1024
				#
				# dh_file = ${certdir}/dh

				#
				#  If your system doesn't have /dev/urandom,
				#  you will need to create this file, and
				#  periodically change its contents.
				#
				#  For security reasons, FreeRADIUS doesn't
				#  write to files in its configuration
				#  directory.
				#
				# random_file = /dev/urandom

				#
				#  The default fragment size is 1K.
				#  However, it's possible to send much more data than
				#  that over a TCP connection.  The upper limit is 64K.
				#  Setting the fragment size to more than 1K means that
				#  there are fewer round trips when setting up a TLS
				#  connection.  But only if the certificates are large.
				#
				fragment_size = 8192

				#  include_length is a flag which is
				#  by default set to yes If set to
				#  yes, Total Length of the message is
				#  included in EVERY packet we send.
				#  If set to no, Total Length of the
				#  message is included ONLY in the
				#  First packet of a fragment series.
				#
		#       include_length = yes

				#  Check the Certificate Revocation List
				#
				#  1) Copy CA certificates and CRLs to same directory.
				#  2) Execute 'c_rehash <CA certs&CRLs Directory>'.
				#    'c_rehash' is OpenSSL's command.
				#  3) uncomment the line below.
				#  5) Restart radiusd
		#       check_crl = yes
				ca_path = ${cadir}

				# OpenSSL does not reload contents of ca_path dir over time.
				# That means that if check_crl is enabled and CRLs are loaded
				# from ca_path dir, at some point CRLs will expire and
				# RADIUSd will stop authenticating NASes.
				# If ca_path_reload_interval is non-zero, it will force OpenSSL
				# to reload all data from ca_path periodically
				#
				# Flush ca_path each hour
				ca_path_reload_interval = 3600

				#
				#  If check_cert_issuer is set, the value will
				#  be checked against the DN of the issuer in
				#  the client certificate.  If the values do not
				#  match, the certificate verification will fail,
				#  rejecting the user.
				#
				#  This check can be done more generally by checking
				#  the value of the TLS-Client-Cert-Issuer attribute.
				#  This check can be done via any mechanism you choose.
				#
		#       check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd"

				#
				#  If check_cert_cn is set, the value will
				#  be xlat'ed and checked against the CN
				#  in the client certificate.  If the values
				#  do not match, the certificate verification
				#  will fail rejecting the user.
				#
				#  This check is done only if the previous
				#  "check_cert_issuer" is not set, or if
				#  the check succeeds.
				#
				#  In 2.1.10 and later, this check can be done
				#  more generally by checking the value of the
				#  TLS-Client-Cert-Common-Name attribute.  This check
				#  can be done via any mechanism you choose.
				#
		#       check_cert_cn = %{User-Name}
		#
				# Set this option to specify the allowed
				# TLS cipher suites.  The format is listed
				# in "man 1 ciphers".
				cipher_list = $ENV{FREERADIUS_SITES_TLS_CIPHER}

				# If enabled, OpenSSL will use server cipher list
				# (possibly defined by cipher_list option above)
				# for choosing right cipher suite rather than
				# using client-specified list which is OpenSSl default
				# behavior. Having it set to yes is a current best practice
				# for TLS
				cipher_server_preference = no

				#
				#  Older TLS versions are deprecated.  But for RadSec,
				#  we CAN allow TLS 1.3.
				#
				tls_min_version = "1.2"
				tls_max_version = "1.3"

				#
				#  Session resumption / fast reauthentication cache.
				#
				#  The cache contains the following information:
				#
				#  session Id - unique identifier, managed by SSL
				#  User-Name  - from the Access-Accept
				#  Stripped-User-Name - from the Access-Request
				#  Cached-Session-Policy - from the Access-Accept
				#
				#  The "Cached-Session-Policy" is the name of a
				#  policy which should be applied to the cached
				#  session.  This policy can be used to assign
				#  VLANs, IP addresses, etc.  It serves as a useful
				#  way to re-apply the policy from the original
				#  Access-Accept to the subsequent Access-Accept
				#  for the cached session.
				#
				#  On session resumption, these attributes are
				#  copied from the cache, and placed into the
				#  reply list.
				#
				#  You probably also want "use_tunneled_reply = yes" when using fast session resumption.
				#
				cache {
					  #
					  #  Enable it.  The default is "no".
					  #  Deleting the entire "cache" subsection
					  #  Also disables caching.
					  #
						#
						#  As of version 3.0.14, the session cache requires the use
						#  of the "name" and "persist_dir" configuration items, below.
						#
						#  The internal OpenSSL session cache has been permanently
						#  disabled.
						#
					  #  You can disallow resumption for a
					  #  particular user by adding the following
					  #  attribute to the control item list:
					  #
					  #         Allow-Session-Resumption = No
					  #
					  #  If "enable = no" below, you CANNOT
					  #  enable resumption for just one user
					  #  by setting the above attribute to "yes".
					  #
					  enable = no

					  #
					  #  Lifetime of the cached entries, in hours.
					  #  The sessions will be deleted after this
					  #  time.
					  #
					  lifetime = 24 # hours

					  #
					  #  Internal "name" of the session cache.
					  #  Used to distinguish which TLS context
					  #  sessions belong to.
					  #
					  #  The server will generate a random value
					  #  if unset. This will change across server
					  #  restart so you MUST set the "name" if you
					  #  want to persist sessions (see below).
					  #
					  #  If you use IPv6, change the "ipaddr" below
					  #  to "ipv6addr"
					  #
					  #name = "TLS ${..ipaddr} ${..port} ${..proto}"

					  #
					  #  Simple directory-based storage of sessions.
					  #  Two files per session will be written, the SSL
					  #  state and the cached VPs. This will persist session
					  #  across server restarts.
					  #
					  #  The server will need write perms, and the directory
					  #  should be secured from anyone else. You might want
					  #  a script to remove old files from here periodically:
					  #
					  #    find ${logdir}/tlscache -mtime +2 -exec rm -f {} \;
					  #
					  #  This feature REQUIRES "name" option be set above.
					  #
					  #persist_dir = "${logdir}/tlscache"
				}

				#
				#  Require a client certificate.
				#
				require_client_cert = yes

				#
				#  As of version 2.1.10, client certificates can be
				#  validated via an external command.  This allows
				#  dynamic CRLs or OCSP to be used.
				#
				#  This configuration is commented out in the
				#  default configuration.  Uncomment it, and configure
				#  the correct paths below to enable it.
				#
				verify {
						#  A temporary directory where the client
						#  certificates are stored.  This directory
						#  MUST be owned by the UID of the server,
						#  and MUST not be accessible by any other
						#  users.  When the server starts, it will do
						#  "chmod go-rwx" on the directory, for
						#  security reasons.  The directory MUST
						#  exist when the server starts.
						#
						#  You should also delete all of the files
						#  in the directory when the server starts.
		#               tmpdir = /tmp/radiusd
						# tmpdir = /startechnica/freeradius/tmp

						#  The command used to verify the client cert.
						#  We recommend using the OpenSSL command-line
						#  tool.
						#
						#  The ${..ca_path} text is a reference to
						#  the ca_path variable defined above.
						#
						#  The %{TLS-Client-Cert-Filename} is the name
						#  of the temporary file containing the cert
						#  in PEM format.  This file is automatically
						#  deleted by the server when the command
						#  returns.
		#               client = "/path/to/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}"
				}
		}
}

clients radsec {
		client 127.0.0.1 {
				ipaddr = 127.0.0.1

				#  Ensure that this client is TLS *only*.
				proto = tls

				#  TCP clients can have any shared secret.
				#  TLS clients MUST have the shared secret set to "radsec".  Or, for "proto = tls", you can omit the secret, and it will
				#  automatically be set to "radsec".
				# secret = radsec
				secret = $ENV{FREERADIUS_CLIENTS_SECRET}

				#  You can also use a "limit" section here.
				#  See raddb/clients.conf for examples.
				#
				#  Note that BOTH limits are applied.  You should therefore set the "listen" limits higher than the ones for each individual
				#  client.
		}
}

#  When a request is proxied to a TLS-enabled home server, the TLS parameters are available via the expansion:
#
#       %{proxy_listen: ... }
#
#  The contents of the expansion are the same as described above with the %{listen: ... } expansion, and have similar meanings.  "client" in this case is the proxy (this system)
#  and "server" is the remote system (home server).
#
#  Note that the %{proxy_listen: ... } parameters are available only AFTER the connection has been made to the home server.
home_server tls {
		ipaddr = 127.0.0.1
		port = $ENV{FREERADIUS_SITES_TLS_PORT}

		# type can be the same types as for the "listen" section/
		# e.g. auth, acct, auth+acct, coa
		type = auth
		secret = radsec
		proto = tcp
		status_check = none

		tls {
				#
				#  Similarly to HTTP, the client can use Server Name
				#  Indication to inform the RadSec server of which
				#  domain it is requesting.  This selection allows
				#  multiple sites to exist at the same IP address.
				#
				#  For example, and identity provider could host
				#  multiple sites, but present itself with one public
				#  IP address.
				#
				#  SNI also permits the use of a load balancer such as
				#  haproxy.  That load balancer can terminate the TLS
				#  connection, and then use SNI to route the
				#  underlying RADIUS TCP traffic to a particular host.
				#
				#  Note that "hostname" here is only for SNI, and is NOT
				#  the hostname or IP address we connect to.  For that,
				#  see "ipaddr", above.
				#
		#       hostname = "example.com"

				private_key_password = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_PASSWORD}
				# private_key_file = ${certdir}/client.pem
				private_key_file = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_FILE}

				#  If Private key & Certificate are located in
				#  the same file, then private_key_file &
				#  certificate_file must contain the same file
				#  name.
				#
				#  If ca_file (below) is not used, then the
				#  certificate_file below MUST include not
				#  only the server certificate, but ALSO all
				#  of the CA certificates used to sign the
				#  server certificate.
				# certificate_file = ${certdir}/client.pem
				certificate_file = $ENV{FREERADIUS_SITES_TLS_CERTIFICATE_FILE}

				#  Trusted Root CA list
				#
				#  ALL of the CA's in this list will be trusted to issue client certificates for authentication.
				#
				#  In general, you should use self-signed certificates for 802.1x (EAP) authentication.
				#  In that case, this CA file should contain *one* CA certificate.
				#
				#  This parameter is used only for EAP-TLS,
				#  when you issue client certificates.  If you do
				#  not use client certificates, and you do not want
				#  to permit EAP-TLS authentication, then delete
				#  this configuration item.
				ca_file = $ENV{FREERADIUS_SITES_TLS_CA_FILE}

				#
				#  For TLS-PSK, the key should be specified dynamically, instead of using a hard-coded psk_identity and psk_hexphrase.
				#
				#  The input to the dynamic expansion will be the PSK
				#  identity supplied by the client, in the
				#  TLS-PSK-Identity attribute.  The output of the
				#  expansion should be a hex string, of no more than
				#  512 characters.  The string should not be prefixed
				#  with "0x".  e.g. "abcdef" is OK.  "0xabcdef" is not.
				#
		#       psk_query = "%{psksql:select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'}"

				#  For DH cipher suites to work, you have to run OpenSSL to create the DH file first:
				#
				#       openssl dhparam -out certs/dh 1024
				#
				# dh_file = ${certdir}/dh
				# random_file = /dev/urandom

				#
				#  The default fragment size is 1K.
				#  However, TLS can send 64K of data at once.
				#  It can be useful to set it higher.
				#
				fragment_size = 8192

				#  include_length is a flag which is
				#  by default set to yes If set to
				#  yes, Total Length of the message is
				#  included in EVERY packet we send.
				#  If set to no, Total Length of the
				#  message is included ONLY in the
				#  First packet of a fragment series.
				#
		#       include_length = yes

				#  Check the Certificate Revocation List
				#
				#  1) Copy CA certificates and CRLs to same directory.
				#  2) Execute 'c_rehash <CA certs&CRLs Directory>'.
				#    'c_rehash' is OpenSSL's command.
				#  3) uncomment the line below.
				#  5) Restart radiusd
		#       check_crl = yes
				ca_path = ${cadir}

			   #
			   #  If check_cert_issuer is set, the value will
			   #  be checked against the DN of the issuer in
			   #  the client certificate.  If the values do not
			   #  match, the certificate verification will fail,
			   #  rejecting the user.
			   #
			   #  In 2.1.10 and later, this check can be done
			   #  more generally by checking the value of the
			   #  TLS-Client-Cert-Issuer attribute.  This check
			   #  can be done via any mechanism you choose.
			   #
		#		check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd"

			   #
			   #  If check_cert_cn is set, the value will
			   #  be xlat'ed and checked against the CN
			   #  in the client certificate.  If the values
			   #  do not match, the certificate verification
			   #  will fail rejecting the user.
			   #
			   #  This check is done only if the previous
			   #  "check_cert_issuer" is not set, or if
			   #  the check succeeds.
			   #
			   #  In 2.1.10 and later, this check can be done
			   #  more generally by checking the value of the
			   #  TLS-Client-Cert-Common-Name attribute.  This check
			   #  can be done via any mechanism you choose.
			   #
		#       check_cert_cn = %{User-Name}
		#
				# Set this option to specify the allowed TLS cipher suites.  The format is listed in "man 1 ciphers".
				cipher_list = $ENV{FREERADIUS_SITES_TLS_CIPHER}
		}

}

home_server_pool tls {
	type = fail-over
	home_server = tls
}

realm tls {
	auth_pool = tls
}