#  -*- text -*-
#
#
#  $Id: 6e6e0649ec4ec5f6cfd630d0af495d7149f8eb09 $

#######################################################################
#
#  = EAP Module
#
#  The `eap` module takes care of all EAP authentication as described in RFC 3579.
#
#  [WARNING]
#  ====
#  Whatever you do, do NOT set 'Auth-Type := ::EAP'.  The server is smart enough
#  to figure this out on its own.
#
#  The most common side effect of setting 'Auth-Type := ::EAP' is that the users
#  then cannot use ANY other authentication method.
#  ====
#

#
#  ## Configuration Settings
#
eap {
	#
	#  require_identity_realm:: Require the the EAP Identity provided contains
	#  a realm.
	#
	#  If `require_identity_realm` is `nai`, the EAP identity provided must
	#  end with `@<label0>.<label1>[.<labelN>]`, i.e. an '@' followed by at least
	#  two DNS labels.
	#
	#  If `require_identity_realm` is `yes`, the EAP identity provided must
	#  either match the NAI format described above, or a `Stripped-User-Domain`
	#  attribute must be present in the request list.
	#  This validation mode is intended to be user where Windows machine
	#  authentication is intermixed with user authentication.
	#
	#  If `require_identity_realm` is `no`, no identity format checks are performed.
	#  It is NOT recommended to use this value.  Future security standards will
	#  key off the NAI realm to validate the certificate we (the EAP server) present.
	#  If you do not require an NAI realm be present in the EAP identity string,
	#  your users will not be able to take advantage of this added security when
	#  it is enabled by OS and device vendors.
	#
#	require_identity_realm = nai

	#
	#  default_eap_type:: The default EAP submodule to invoke when an `EAP-Identity`
	#  response is received.
	#
	#  If a `default_eap_type` value is not provided, enabled EAP submodules will be
	#  queried to determine if they recognise the provided EAP-Identity.
	#  If no submodules recognise the identity, the first `type` value listed below
	#  will be used.
	#
	#  If the `control.EAP-Type` attribute is set, then that EAP type takes precedence
	#  over any configured or inferred EAP-Type.
	#
	#  It is generally recommended to NOT set `default_eap_type`, and instead order
	#  the `type` configuration items appropriately.
	#
#	default_eap_type = md5

	#
	#  ignore_unknown_eap_types::
	#
	#  There are many EAP types, but the server has support for only a
	#  limited subset.  If the server receives a request for an EAP type it
	#  does not support, then it normally rejects the request.  By setting
	#  this configuration to `yes`, you can tell the server to instead keep
	#  processing the request.  Another module MUST then be configured to
	#  proxy the request to another RADIUS server which supports that EAP
	#  type.
	#
	#  NOTE: If another module is NOT configured to handle the request, then the
	#  request will still end up being rejected.
	#
	ignore_unknown_eap_types = no

	#
	#  ## Allowed EAP-types
	#
	#  type:: Only EAP types listed below with a `type = <EAP-Type>` pair will be allowed.
	#
	#  If the `control.EAP-Type` attribute is set, then that is used to form the list of
	#  allowed EAP types, with the first instance being the default type and others also
	#  being allowed.
	#
	#  Setting an EAP type in `control.EAP-Type` which is not allowed below, will not have
	#  any effect, since this list determines which methods are loaded and potentially
	#  available.
	#
	type = md5
#	type = pwd
	type = gtc
	type = tls
	type = ttls
	type = mschapv2
	type = peap
#	type = fast
#	type = aka
#	type = sim

	#
	#  ### EAP-MD5
	#
	#  WARNING: EAP-MD5 authentication cannot be used for wireless
	#  connections.  It is insecure, and does not provide for dynamic WEP
	#  keys or WPA enterprise.

	#
	md5 {
	}

	#
	#  ### EAP-PWD (Secure password-based authentication)
	#
	#  In v4, the "known good" password is taken from the `&request.control.Password.Cleartext` list,
	#  as is done by other modules. The change from v3 is that the `inner-tunnel` virtual server
	#  is no not used.
	#
#	pwd {
#		group = 19

#		server_id = theserver@example.com

		#
		#  fragment_size:: This has the same meaning as for TLS.
		#
#		fragment_size = 1020
#	}

	#
	#  ### Generic Token Card
	#
	#  Currently, this is only permitted inside of `EAP-TTLS`, or `EAP-PEAP`.
	#  The module `challenges` the user with text, and the response from the
	#  user is taken to be the `User-Password`.
	#
	#  WARNING: Proxying the tunneled `EAP-GTC` session is a bad idea, the users
	#  password will go over the wire in plain-text, for anyone to see.
	#
	gtc {
		#
		#  challenge:: The default challenge, which many clients ignore.
		#
#		challenge = "Password: "

		#
		#  auth_type::
		#
		#  The plain-text response which comes back is put into a
		#  `User-Password` attribute, and passed to another module for
		#  authentication.  This allows the `EAP-GTC` response to be
		#  checked against plain-text, or crypt'd passwords.
		#
		#  If you say "Local" instead of "PAP", then the module will
		#  look for a `User-Password` configured for the request, and do
		#  the authentication itself.
		#
		auth_type = PAP
	}

	#
	#  ## Common TLS configuration for TLS-based EAP types
	#
	#  See `doc/raddb/certs/index.adoc` for additional comments on certificates.
	#
	#  If OpenSSL was not found at the time the server was built, the `tls`,
	#  `ttls`, and `peap` sections will be ignored.
	#
	#  If you do not currently have certificates signed by a trusted CA you
	#  may use the 'snakeoil' certificates. Included with the server in
	#  `raddb/certs`.
	#
	#  If these certificates have not been auto-generated:
	#
	#    cd raddb/certs
	#    make
	#
	#  These test certificates *SHOULD NOT* be used in a normal
	#  deployment.  They are created only to make it easier to
	#  install the server, and to perform some simple tests with
	#  EAP-TLS, TTLS, or PEAP.
	#
	#  Note that you should NOT use a globally known CA here!
	#  e.g. using a Verisign cert as a "known CA" means that
	#  ANYONE who has a certificate signed by them may be able to
	#  authenticate via EAP-TLS!  This is likely not what you
	#  want.
	#
	#
	#  [NOTE]
	#  ====
	#  As of 4.0 the following TLS config items/config sections have been
	#  removed.  Equivalent functionality is available.
	#  ====
	#
	#  [options="header,autowidth"]
	#  |===
	#  | Config item | Replacement
	#
	#  | `verify_client_cert_cmd`
	#  | Unlang policy in the `verify certificate { ... }` section of the specified `virtual_server`.
	#
	#  | `check_cert_issuer`
	#  | Unlang policy in the `verify certificate { ... }` section of the specified `virtual_server`.
	#
	#  | `check_cert_cn`
	#  | Unlang policy in the `verify certificate { ... }` section of the specified `virtual_server`.
	#
	#  | `ocsp`
	#  | rlm_ocsp call in the `verify certificate { ... }` section of the specified `virtual_server`.
	#
	#  | `staple`
	#  | rlm_ocsp call in the `staple certificate { ... }` section of the specified `virtual_server`.
	#  |===
	#
	tls-config tls-common {
		#
		#  virtual_server:: The virtual server used for checking and saving TLS data.
		#
		#  When the module receives certificate checks and stateful
		#  session resumption requests, that information will be passed
		#  through a virtual server.  This virtual server typically runs
		#  policies which verifies the certificate, or loads / stores
		#  session resumption data.
		#
		#  The virtual server must specify `namespace = tls`, and may contain
		#  the following sections:
		#
		#  [options="header,autowidth"]
		#  |===
		#  | Section | Purpose
		#
		#  | `load session { ... }`
		#  | Load stateful session information from a cache.
		#
		#  | `store session { ... }`
		#  | Store stateful session information in a cache.
		#
		#  | `clear session { ... }`
		#  | Clear stateful session information from a cache.
		#
		#  | `verify certificate { ... }` |
		#  | Apply policies based on the client certificate presented.
		#
		#  | `staple certificate { ... }`
		#  | Gather stapling information for one or more of our certificates.
		#  |===
		#
		#  More information about the various sections can be found in the virtual server
		#  `sites-available/tls-session`.
		#
#		virtual_server = tls-session

		#  auto_chain::
		#
		#  OpenSSL will automatically create certificate chains, unless
		#  we tell it to not do that.  The problem is that it sometimes
		#  gets the chains right from a certificate signature view, but
		#  wrong from the clients view.
		#
		#  NOTE: When setting `auto_chain = no`, the server `chain {}`
		#  section(s) below MUST include the full certificate chain.
		#
#		auto_chain = no

		#
		#  .A chain of certificates to present to the client
		#
		#  Multiple chain sections can be specified to allow different
		#  chains for different key types (RSA, DSA, DH, EC).
		#
		#  If multiple chains for the same key type are specified
		#  the last chain to be processed will be used for that
		#  key type.
		#
		#  WARNING: The server automatically selects a chain based on
		#  the cipher agreed by the client and server. For example, if
		#  the client includes ECC ciphers in its request, but the
		#  server only has an RSA certificate, then the authentication
		#  is likely to fail.  i.e. The client is asking the server to
		#  use an ECC cipher and ECC certificate, but the server has no
		#  ECC certificate available.
		#
		#  The key type does not need to be explicitly specified as
		#  it is determined from the provided certificate.
		#
		chain rsa {
			#
			#  format:: The format of the certificate(s) and private key file.
			#
			#  May be one of `PEM`, `DER` or `ASN1` (ASN1 is an alias for `DER`).
			#
			#  Most Linux systems use PEM format.  Windows and other
			#  systems usually use DER.
			#
#			format = "PEM"

			#
			#  certificate_file:: File which contains the certificate presented
			#  as the "server certificate" to the client.
			#
			#  If the PEM format is used, the `certificate_file`
			#  should contain the server certificates, along with
			#  any intermediate CAs up to the root CA.  The client
			#  is not normally configured with the intermediate CAs,
			#  but it needs them to verify the server certificate.
			#  The server therefore has to supply the intermediate
			#  CAs to the client during the authentication process.
			#
			#  [NOTE]
			#  ====
			#  If `verify_mode` (below) is set to `hard` or `soft`
			#  all intermediary CAs and the Root CA need to be
			#  included in the `certificate_file`.
			#
			#  If the file includes multiple certificates, they MUST
			#  be listedin order from server certificate (first in
			#  the file) to intermediary CAs (second) to Root CA
			#  (last in the file) as per RFC 4346 Section 7.4.2 (see
			#  certificate_list)
			#
			#  If the DER format is used, the `certificate_file`
			#  should contain ONLY the server's certificate.  One
			#  or more `ca_file` items should be used to load
			#  the intermediate CAs and the Root CA.
			#  ====
			#
			#  We recommend using `ca_file` to load the
			#  root CAs, instead of putting them in the
			#  `certificate_file`.
			#
			certificate_file = ${certdir}/rsa/server.pem

			#
			#  ca_file::  File which contains the root CA.
			#
			#  THis configuration item allows the server to load
			#  additional intermediate CA or Root CA when creating
			#  certificate chains.  Multiple "ca_file"
			#  configurations items may be specified in order to
			#  load multiple certificates.
			#
			#  When multiple `ca_file` entries are used, the server
			#  will still present only one server certificate (from
			#  `certificate_file`) to the clients.  The main use for
			#  multiple `ca_file` entries is to permit the use of
			#  EAP-TLS with client certificates from multiple Root
			#  CAs.
			#
			#  If the root CA does not issue client certificates, or
			#  if only one root CA is , then the `ca_file`
			#  configuration can be commented out (at least when PEM
			#  format is used).
			#
			ca_file = ${certdir}/rsa/ca.pem

			#
			#  private_key_password:: The password which is used to encrypt the private key.
			#
			#  If the private key is not encrypted, this configuration item
			#  will have no effect.
			#
			#  In general, there is little security benefit in
			#  encrypting the `private_key_file` with a password.
			#
			private_key_password = whatever

			#
			#  private_key_file:: File which contains the private key.
			#
			#  If the Private key & Certificate are located in the same file,
			#  then `private_key_file` & `certificate_file` must contain the
			#  same file name.
			#
			private_key_file = ${certdir}/rsa/server.key

			#
			#  verify_mode:: How we verify the certificate chain.
			#
			#  During startup the server attempts to precompile the certificate chain
			#  from server certificate to Root CA.  This configuration item specifies
			#  what happens if compilation fails.
			#
			#  [options="header,autowidth"]
			#  |===
			#  | Error | Description
			#  | hard  | Error out if we cannot build a complete certificate chain.
			#  | soft  | Warn if we cannot build a complete certificate chain.
			#  | none  | Stay silent if we cannot build a complete certificate chain.
			#  |===
			#
			#  The default is `hard`.  The only time this should be changed is if
			#  you want to limit the number of intermediary CAs sent to the
			#  client by not including them in the chain.
			#
			#  [NOTE]
			#  ====
			#  * Depending on the value of `auto_chain` we may still be able to
			#    build a complete chain, but this will be done at runtime.
			#
			#  * `auto_chain` has no effect on which certificates are considered
			#  for pre-compilation.  Only those listed in this `chain {}` section
			#  will be used.
			#  ====
			#
#			verify_mode = "hard"

			#
			#  include_root_ca:: Whether or not the root CA is included in the
			#  certificate chain.
			#
			#  The Root CA should already be known/trusted by the client so it is
			#  usually not needed unless the client is particularly poorly behaved.
			#
			#  NOTE: The Root CA must still be available for creating certificate chains to
			#  succeed even if `include_root_ca = no`.
			#
			#  Default: `no`.
			#
			include_root_ca = no
		}

		#
		#  ### ECC certificate chain for key agility
		#
		#  This is disabled by default, see the warning above.
		#
		#  If your supplicants propose a mix of different
		#  types of ciphers _and_ have all of the CA keys for
		#  each type of certificate, then multiple chains can be
		#  enabled simultaneously.
		#
#		chain ecc {
#			certificate_file = ${certdir}/ecc/server.pem
#			ca_file = ${certdir}/ecc/ca.pem
#			private_key_password = whatever
#			private_key_file = ${certdir}/ecc/server.key
#		}

		#
		#  ## Server certificate
		#
		#  The server certificate may also be specified at
		#  runtime on a per session basis.  In that use-case,
		#  the certificate file must consist of the
		#  certificate and private key, PEM encoded.  The
		#  password should either be set above with
		#  `password`, or the certificate should have no
		#  password.
		#
		#  The file should be provided as the attribute:
		#
		#      &control.TLS-Session-Cert-File
		#
		#  If there are any errors loading or verifying the
		#  certificate, then authentication will fail.
		#
		#  This configuration can be used to periodically
		#  verify correct supplicant behaviour, by presenting
		#  an untrusted or invalid server certificate and
		#  verifying that the supplicant returns the correct
		#  TLS alert (available in Module-Failure-Message).
		#
		#  NOTE: After receiving a fatal alert, TLS negotiation
		#  cannot continue, but as most supplicants will retry
		#  enthusiastically, so this probably won't be an issue.
		#

		#
		#  ca_file:: Trusted Root CA list
		#
		#  ALL of the CA's in this list will be trusted to issue client
		#  certificates for authentication.
		#
		#  NOTE: You should not use a public CA here.  This should either be
		#  set to a certificate chain for your institution's CA,
		#  or to a self signed Root CA.
		#
		ca_file = ${cadir}/rsa/ca.pem

		#
		#  psk_identity:: Default identity to present for PSK.
		#
		#  If OpenSSL supports TLS-PSK, then we can use a PSK identity
		#  and (hex) password.
		#
		#  If using a fixed identity, it must be the same on
		#  the client.  The passphrase must be a hex value,
		#  and can be up to 256 hex characters.
		#
#		psk_identity = "test"
#		psk_hexphrase = "036363823"

		#
		#  WARNING: Dynamic queries for the `PSK`.  If `TLS-PSK` is used,
		#  and `psk_query` is set, then you MUST NOT use
		#  `psk_identity` or `psk_hexphrase`.
		#

		#
		#  psk_query:: Dynamically obtain the PSK from a query.
		#
		#  Instead, use a dynamic expansion similar to the one
		#  below.  It keys off of TLS-PSK-Identity.  It should
		#  return a of string no more than 512 hex characters.
		#  That string will be converted to binary, and will
		#  be used as the dynamic PSK hexphrase.
		#
		#  Note that this query is just an example.  You will
		#  need to customize it for your installation.
		#
#		psk_query = "%sql(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 2048
		#
		#  The DH parameters will usually be ignored in FIPS mode.
		#
		dh_file = ${certdir}/dh

		#
		#  fragment_size:: Limit for size of EAP fragments.
		#
		#  This can never exceed the size of a RADIUS packet (4096
		#  bytes), and is preferably less than half of that, to leave
		#  room for other attributes in RADIUS packet.  In most cases,
		#  the maximum EAP packet length is limited to the Ethernet MTU,
		#  which between `1500 - 1600` bytes.
		#
		#  In these cases, fragment size should be `1024` or less.  Note
		#  also that the EAP RFCs say that EAP implementations MUST use
		#  fragments of at least 1020 bytes!  Many implementations will
		#  work with smaller values, but it is not guaranteed.
		#
#		fragment_size = 1024

		#
		#  ca_path:: Directory where additional CAs are located.
		#
		#  After placing files in this directory, the OpenSSL command
		#  `c_rehash` should be used to update the local files used by OpenSSL.
		#
		#  Most systems will only use one server certificate,
		#  and one root CA.  Where client certificates are
		#  used, they are usually also issued from that same
		#  root CA.  In which case the `ca_path` configuration
		#  is not necessary.  All certificates can be placed
		#  into the file which is configured in `certificate_file`.
		#
		#  The main reason to use multiple `ca_file` entries,
		#  or the `ca_path` configuration, is when the server
		#  is expected to authenticate client certificates issued by multiple CAs.
		#
		ca_path = ${cadir}

		#
		#  cipher_list:: Set the list of allowed TLS cipher suites.
		#
		#  The format is listed by OpenSSL in `man 1 ciphers`.
		#
		#  NOTE: For `EAP-FAST`, use "ALL:!EXPORT:!eNULL:!SSLv2"
		#
		cipher_list = "DEFAULT"

		#
		#  cipher_server_preference:: Prefer the server cipher list.
		#
		#  If enabled, OpenSSL will use the server cipher list (possibly
		#  defined by the `cipher_list` option above) for choosing right
		#  cipher suite, instead of using the client-specified list which is
		#  OpenSSl default behavior. Having it set to 'yes' is best
		#  practice for TLS.
		#
		cipher_server_preference = yes

		#
		#  tls_max_version:: Maximum TLS version we allow.
		#
		#  [NOTE]
		#  ====
		#  * SSLv2 and SSLv3 are permanently disabled due to security
		#  issues.
		#
		#  * We STRONGLY RECOMMEND that TLS 1.0 and TLS 1.1 be disabled.
		#  They are insecure and SHOULD NOT BE USED.
		#  ====
		#
#		tls_max_version = 1.2

		#
		#  tls_min_version:: Minimum TLS version we allow.
		#
		#  [NOTE]
		#  ====
		#  Prevents versions < tls_min_version from being negotiated.
		#  In general the higher the tls_min_version the more secure
		#  the protocol, but the narrower the range of supported TLS
		#  clients.
		#
		#  SSLv2 and SSLv3 are permanently disabled due to security
		#  issues.
		#  ====
		#
#		tls_min_version = 1.2

		#
		#  ecdh_curve:: Elliptical cryptography configuration.
		#
		#  Should be a colon-separated list of curve names.
		#
		#  For supported curve names, please run the command:
		#
		#	openssl ecparam -list_curves
		#
		ecdh_curve = prime256v1

		#
		#  verify:: Parameters for controlling client cert chain
		#  verification.
		#
		#  Certificate verification is performed in two phases.
		#  The first is handled by the SSL library which checks
		#  whether a trusted chain of certificates can be built
		#  between the certificates loaded from `ca_file` or
		#  found in `ca_path`.
		#
		#  The second (optional) phase is performed using the
		#  `verify * { ... }` sections of the tls
		#  `virtual_server`.
		#
		verify {
			#
			#  mode:: Which certificates in the verification chain
			#  should be checked.
			#
			#  Certificate verification is performed in two phases.
			#  The first is handled by the SSL library which checks
			#  whether a trusted chain of certificates can be built
			#  between the certificates loaded from `ca_file` or
			#  found in `ca_path`.
			#
			#  The SSL library also checks that the the correct usage
			#  OIDs are present in the presented client certificate
			#  and that none of the certificates have expired.
			#
			#  [options="header,autowidth"]
			#  |===
			#  | Value | Description
			#
			#  | `disabled`
			#  | Don't verify any certificates.
			#
			#  | `all`
			#  | Verify all certificates.  Check none have been
			#    revoked via CRL, and that all are trusted.
			#
			#  | `untrusted`
			#  | Verify all untrusted certificates,
			#    i.e. those which were presented by the client
			#    and not loaded on startup.
			#
			#  | `client-and-issuer`
			#  | Verify the client certificate and its issuer.
			#
			#  | `client`
			#  | Only verify the client certificate.
			#  |===
			#
			#  It is recommended to leave mode as `all` except
			#  when debugging, or in an emergency situation.
			#
#			mode = all

			#
			#  attribute_mode:: Which client certificates should
			#  be converted to attributes for use in the
			#  `verify * { ... }` sections of the specified
			#  `virtual_server`.
			#
			#  Attributes created during certificate processing
			#  will be placed in the `&session-state` list.
			#  This is to simplify session-resumption, as the
			#  contents of this list also contains session data
			#  for stateful resumption, and this list is encoded
			#  in the session-ticket for stateless resumption.
			#
			#  [options="header,autowidth"]
			#  |===
			#  | Value | Description
			#
			#  | `disabled`
			#  | Don't produce any attributes.
			#
			#  | `all`
			#  | Create attributes for all certificates from
			#    the root, to the presented client certificate.
			#
			#  | `untrusted`
			#  | Create attributes for untrusted certificates,
			#    i.e. those which were presented by the client
			#    and not loaded on startup.
			#
			#  | `client-and-issuer`
			#  | Create attributes for the client certificate
			#    and its issuer.
			#
			#  | `client`
			#  | Only create attributes for the client
			#    certificate.
			#  |===
			#
			#  [NOTE]
			#  ====
			#  Attribute generation is only performed on full
			#  handshake, or where we detect that attributes
			#  are missing from the &session-state list during
			#  stateful session-resumption.
			#
			#  Certificate attributes will usually be retrieved
			#  from the the session-ticket in the case of
			#  stateless session-resumption.
			#  ====
			#
#			attribute_mode = client-and-issuer

			#
			#  check_crl:: Check the Certificate Revocation List.
			#
			#  Will check CRLs for all certificates in the certificate chain.
			#
			#  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 lines below.
			#  4. Restart radiusd.
			#
#			check_crl = yes

			#
			#  allow_expired_crl:: Accept an expired Certificate Revocation List.
			#
#			allow_expired_crl = no

			#
			#  allow_not_yet_valid_crl:: Accept a not-yet-valid Certificate Revocation List.
			#
#			allow_not_yet_valid_crl = no
		}
		#
		#  ### TLS Session resumption
		#
		#  Once authentication has completed, the TLS client may be
		#  provided with a session ticket which it presents
		#  during the next authentication attemp.
		#
		#  Presenting a session ticket allows the client to skip the
		#  majority of TLS tunnel setup during its next authentication
		#  session.  It also means that any "inner" authentication is
		#  skipped, which means that any "inner" policies need to be
		#  cached.
		#
		#  Enabling `Session-Resumption` is highly recommended for sites
		#  using slow authentication backends such as winbindd/Active
		#  Directory, and for access federations operating over the
		#  internet, such as Eduroam.
		#
		#  For EAP-TLS, the server also caches the client certificate,
		#  as it is not supplied during session resumption.  Caching the
		#  client certificate allows the server to re-apply policy rules
		#  for the client certificate, along with certificate expiry time.
		#
		#  Many of the configuration items in this section increase
		#  security, but are disabled by default.  The intent is to
		#  allow the server to work in the widest possible
		#  circumstances, while still being reasonably secure.  In the
		#  most common case (single EAP module, single server
		#  certificate), this configuratiuon is acceptable.
		#
		#  However, we still recommend enabling all of the security
		#  configurations below.  If enabling them does not cause an
		#  issue in your environment, then there is no cost to leaving
		#  them enabled.  They should only be disabled if clients are
		#  unable to connect when the configurations are enabled.
		#
		#  [NOTE]
		#  ====
		#  You must ensure that any attributes required for policy
		#  decisions are cached along with the TLS session
		#  data. This is usually done by placing policy attributes in the
		#  `&session-state` list, or in the case of EAP-PEAP, EAP-TTLS and
		#  EAP-FAST, the `&parent.session-state` list (i.e. in the request
		#  which sets up the TLS part of the authentication attempt).
		#
		#  Caching this data means that the policies are cached at the
		#  same time as, and along with the session resumption data.  In
		#  most cases, it is sufficient to cache the name of a policy,
		#  so that the named policy can be re-applied on session resumption.
		#  ====
		#
		session {
			#
			#  mode:: What type of session caching should be allowed.
			#
			#  [options="header,autowidth"]
			#  |===
			#  | Value | Description
			#
			#  | `disabled`
			#  | Don't allow any kind of session resumption.
			#
			#  | `stateful`
			#  | Use <= TLS 1.2 style stateful session resumption.
			#    A unique session-identifier is provided to the client.
			#    The client provides this identifier during the next
			#    authentication attempt, and we lookup session information
			#    based on this identifier.
			#    A `virtual_server` with `load session { ... }`,
			#    `store session { ... }` and `clear session { ... }`
			#    sections must be configured.
			#
			#  | `stateless`
			#  | Allow session-ticket based resumption.  This requires no
			#    external support.  All information required for resumption
			#    is sent to the TLS client in an encrypted session-ticket.
			#    The client returns this ticket during the next
			#    authentication attempt.
			#
			#  | `auto`
			#  | Choose an appropriate session resumption type based on
			#    the TLS version used and whether a `virtual_server` is
			#    configured and has the required `session` sections.
			#  |===
			#
			#  It is recommended to set `mode = auto` *and* to provide a
			#  correctly configured `virtual_server`.
			#
			#  Some clients such as wpa_supplicant do not allow
			#  session tickets by default for TLS < 1.3.
			#
#			mode = auto

			#  name:: Name of the context used for TLS sessions.
			#
			#  This name associates the TLS sessions with a
			#  "namespace" so that they cannot be used for purposes
			#  other than the original (intended) use-case.  This
			#  configuration helps to prevent accidental "leakage"
			#  of session tickes.  For example, if the server uses
			#  multiple server certs, an attacker could try to get a
			#  session ticket for one server identity, and then
			#  resume the session for a different server identity.
			#  Using a session ticket "namespace" makes these
			#  attacks impossible.
			#
			#  If you wish to share session resumption data between
			#  multiple EAP modules or virtual servers, they must
			#  all use the same `name`.
			#
			#  To disable - set to a zero length string "".
			#
			#  NOTE: OpenSSL only allows 32 bytes of session ctx, so
			#  the value provided here is first hashed with SHA256
			#  before being passed to OpenSSL.
			#
#			name = "%{EAP-Type}%interpreter(server)"

			#
			#  lifetime:: The period for which a resumable session remains vali.d
			#
			#  Default is 24hrs in line with RFC 4346.  RFC 8446
			#  requires that ticket lifetimes must not be more than
			#  7 days.
			#
#			lifetime = 86400

			#
			#  require_extended_master_secret:: Only allow session
			#  resumption if an extended master secret has been
			#  created.  This requires client support.
			#
			#  Extended Master Secrets (RFC 7627) are required to
			#  prevent MITM attacks, where the attacker can resume
			#  a session if it can insert itself into the path between
			#  the TLS client and TLS server.
			#
			#  See more at https://mitls.org/pages/attacks/3SHAKE
			#
			#  WARNING: This attack is undetectable by the client.
			#
#			require_extended_master_secret = yes

			#
			#  require_perfect_forward_secrecy:: Only allow session
			#  resumption if a cipher which would allow perfect
			#  forward secrecy has been selected.
			#
#			require_perfect_forward_secrecy = no

			#
			#  session_ticket_key:: Key used to encrypt stateless
			#  session tickets.
			#
			#  Sets a persistent key used to encrypt stateless session
			#  tickets.  If this is not set, then a random key will be
			#  chosen when the server starts.
			#
			#  Where a site has multiple RADIUS servers, it is
			#  useful for them to share a common value for the
			#  `session_ticket_key`.  That way a client can
			#  authenticate against one server, get a session
			#  ticket, and then have that session ticket validated
			#  by a different server.  Such a configuration has
			#  significant positive effects for increasing uptime,
			#  and decreasing server load.
			#
			#  As the key length used by OpenSSL depends on the
			#  version/flavour of OpenSSL being used, the value
			#  provided is fed into a HKDF function (SHA256 of the
			#  key plus "freeradius-session-ticket").  The output of
			#  the HKDF is then used as input to the OpenSSL keying
			#  function.
			#
			#  It is important that a strong key is chosen here.  If the
			#  key were ever revealed, then an attacker could manipulate
			#  the contents of a session ticket.  This could in turn
			#  allow privilege escalation, or if OpenSSL's ticket parsing
			#  code is less than perfect, buffer overflow attacks.
			#
#			session_ticket_key = "super-secret-key"

			#
			#  [NOTE]
			#  ====
			#  As of 4.0 OpenSSL's internal cache has been disabled due to
			#  scoping/threading issues.
			#
			#  The following configuration options are no longer
			#  supported.  TLS session caching is now handled by
			#  FreeRADIUS either using session-tickets (stateless),
			#  or using TLS `virtual_server` and storing/retrieving
			#  sessions to/from an external datastore (stateful).
			#
			#  * `enable`
			#  * `persist_dir`
			#  * `max_entries`
			#  ====
			#
		}
	}

	#
	#  ### EAP-TLS
	#
	#  The common TLS configuration for TLS-based EAP types is given above
	#  in the `tls-config { ... }` section.
	#
	tls {
		#  Point to the common TLS configuration
		tls = tls-common

		#
		#  require_client_cert:: Whether we require a client certificate.
		#
		#  `EAP-TLS` can work without a client certificate, but situations
		#  whether this is useful are quite limited.
		#
		#  Currently only the Hotspot 2.0 R2 standard uses `EAP-TLS`
		#  without a peer certificate.
		#
		#  This is to secure the SSID used to provide connectivity to the OSU
		#  (Online Signup Server).
		#
		#  You can override this configuration item at run-time by setting:
		#
		#    &control.EAP-TLS-Require-Client-Cert = Yes/No
		#
#		require_client_cert = yes

		#
		#  include_length:: Whether we include a length field in the TLS header.
		#
		#  If set to `yes`, the total length of the message is included
		#  in every packet we send. If set to `no`, the total length of
		#  the message is included only in the First packet of a
		#  fragment series.
		#
		#  This configuration item is here only to work around
		#  historical issues with misbehaving clients.  In most cases,
		#  it does not need to be changed.
		#
#		include_length = yes
	}

	#
	#  ### EAP-TTLS
	#
	#  The TTLS module implements the `EAP-TTLS` protocol, which can be
	#  described as EAP inside of Diameter, inside of TLS, inside of EAP,
	#  inside of RADIUS.
	#
	#  NOTE: To use `EAP-TTLS `you must also configure an `inner` method in
	#  `mods-enabled/eap_inner`.
	#
	#  Surprisingly, it works quite well.
	#
	#  When using `PAP`, `GTC`, or `MSCAHPv2` as an inner method, `EAP-TTLS`
	#  is only secure if the supplicant validates the server certificate
	#  presented.  If the client disables certificate validation, then an
	#  attacker can pretend to be the server, and collect user credentials.
	#
	ttls {
		#
		#  tls::  Point to the common TLS configuration
		#
		#  Which `tls-config` section the TLS negotiation parameters
		#  are in - see `EAP-TLS` above for an explanation.
		#
		tls = tls-common

		#
		#  [WARNING]
		#  ====
		#  Both `copy_request_to_tunnel` and `use_tunneled_reply` have been
		#  removed in v4.0.
		#
		#  See the new policy `copy_request_to_tunnel` in
		#  `sites-available/inner-tunnel`, and in `policy.d/eap` for
		#  more information.  ====
		#

		#
		#  virtual_server:: The virtual server used for "inner" authentication.
		#
		#  The inner tunneled request can be sent through a virtual
		#  server which verifies the inner credentials.
		#
		#  If this entry is commented out, the inner tunneled request
		#  will be sent through the virtual server which processed the
		#  outer request.  This configuration is NOT RECOMMENDED.
		#
		virtual_server = "inner-tunnel"

		#
		#  include_length:: Whether we include a length fiel in the TLS header.
		#
		#  This has the same meaning, and overwrites, the same field in
		#  the `tls` configuration, above.  The default value here is
		#  `yes`.
		#
#		include_length = yes

		#
		#  require_client_cert:: Whether we require a client certificate.
		#
		#  `EAP-TTLS` does not require a client certificate.
		#  However, you can require one by setting the
		#  following option. You can also override this option by
		#  setting:
		#
		#    &control.EAP-TLS-Require-Client-Cert = Yes
		#
		#  NOTE: The majority of supplicants do not support using a
		#  client certificate with `EAP-TTLS`, so this option is unlikely
		#  to be useful for most people.
		#
#		require_client_cert = yes
	}

	#
	#  ### EAP-PEAP
	#
	#  The tunneled `EAP` session needs a default `EAP` type which is separate
	#  from the one for the non-tunneled EAP module.  Inside of the TLS/PEAP
	#  tunnel, we recommend using `EAP-MS-CHAPv2`.
	#
	#  When using `GTC`, or `MSCHAPv2` as an inner method, `PEAP` is only
	#  secure if the supplicant is configured to validate the server
	#  certificate.  See the comments above for EAP-TTLS about this topic.
	#
	#  #### Windows compatibility
	#
	#  [IMPORTANT]
	#  ====
	#  * If you see the server send an `Access-Challenge`, and the client never
	#  sends another `Access-Request`, then	*STOP*!
	#
	#  * The server certificate has to have special OID's in it, or else the
	#  Microsoft clients will silently fail.  See the `scripts/xpextensions`
	#  file for details, and the following page
	#  http://support.microsoft.com/kb/814394/en-us
	#
	#  * If is still doesn't work, and you're using Samba, you may be
	#  encountering a Samba bug.
	#  see: https://bugzilla.samba.org/show_bug.cgi?id=6563
	#
	#  * Note that we do not necessarily agree with their explanation. but
	#  the fix does appear to work.
	#  ====
	#
	#  NOTE: To use `PEAP` you must also configure an inner method in
	#  `mods-enabled/eap_inner`.
	#
	peap {
		#
		#  tls::  Point to the common TLS configuration
		#
		#  Which `tls-config` section the TLS negotiation parameters are
		#  in - see `EAP-TLS` above for an explanation.
		#
		tls = tls-common

		#
		#  default_eap_type:: The default EAP type proposed by the server inside of the tunnel.
		#
		#  The tunneled EAP session needs a default EAP type which is
		#  separate from the one for the non-tunneled EAP module.
		#  Inside of the PEAP tunnel, we recommend using MS-CHAPv2, as
		#  that is the default type supported by Windows clients.
		#
		default_eap_type = mschapv2

		#
		#  [NOTE]
		#  ====
		#  Both `copy_request_to_tunnel` and `use_tunneled_reply` have been
		#  removed in v4.0.
		#
		#  See the new policy `copy_request_to_tunnel` in
		#  `sites-available/inner-tunnel`, and in `policy.d/eap`
		#  for more information.
		#  ====
		#

		#
		#  virtual_server:: The virtual server used for "inner" authentication.
		#
		#  The inner tunneled request can be sent through a virtual
		#  server which verifies the inner credentials.
		#
		#  If this entry is commented out, the inner tunneled request
		#  will be sent through the virtual server which processed the
		#  outer request.  This configuration is NOT RECOMMENDED.
		#
		virtual_server = "inner-tunnel"

		#
		#  require_client_cert:: Whether we require a client certificate.
		#
		#  Unlike `EAP-TLS`, `PEAP `does not require a client certificate.
		#  However, you can require one by setting the following
		#  option. You can also override this option by setting
		#
		#	&control.EAP-TLS-Require-Client-Cert = Yes
		#
		#  NOTE: The majority of supplicants do not support using a
		#  client certificate with `PEAP`, so this option is unlikely to
		#  be useful for most people.
		#
#		require_client_cert = yes
	}

	#
	#  ### EAP MS-CHAPv2
	#
	#  NOTE: This is the EAP MS-CHAPv2 sub-module, not the main `mschap`
	#  module.
	#
	#  In order for this sub-module to work, the main `mschap` module MUST
	#  ALSO be configured.
	#
	#  This module is the *Microsoft* implementation of `MS-CHAPv2` in `EAP`.
	#  There is another (*incompatible*) implementation of `MS-CHAPv2 in `EAP` by
	#  Cisco, which *FreeRADIUS does not support*.
	#
	mschapv2 {
		#
		#  auth_type:: Which "authenticate" section is used to authenticate the MS-CHAP data.
		#
#		auth_type = mschap

		#
		#  send_error:: Whether we send an MS-CHAP error on authentication failure.
		#
		#  In early versions of FreeRADIUS, the module never sent the
		#  `MS-CHAP-Error` message to the client.  This worked, but it had
		#  issues when the cached password was wrong.  The server
		#  *should* send `E=691 R=0` to the client, which tells it to
		#  prompt the user for a new password.
		#
		#  CAUTION: The default is `no`, which is known to work.  If you
		#  set `send_error = yes`, then the error message will be sent
		#  back to the client. This *may* help some clients work better,
		#  but *may* also cause other clients to stop working.
		#
#		send_error = no

		#
		#  identity:: The server identifier to send back in the challenge.
		#
		#  It should generally be the host name of the RADIUS server.
		#  Or, some information which uniquely identifies it.
		#
#		identity = "FreeRADIUS"

		#
		#  with_ntdomain_hack:: Windows clients send `User-Name` in the
		#  form of `DOMAIN\User`, but sometimes calculate the
		#  challenge/response based only on the `User` portion.
		#
		#  Setting this value to `yes` makes FreeRADIUS use only the
		#  "user" portion of the `User-Name` for its MS-CHAP
		#  calculations.
		#
		#  If this behavior seems weird and complicated, we agree.
		#  There is no reason for the Windows systems to do something so
		#  unfriendly.  All it does is make life difficult for the
		#  administrator, who has to figure out why MS-CHAP is magically
		#  failing.
		#
		#  Default is `no`.
		#
#		with_ntdomain_hack = yes
	}

	#
	#  ### EAP-FAST
	#
	#  The FAST module implements the EAP-FAST protocol.
	#
	#  NOTE: To use `EAP-FAST` you must also configure an `inner` method in
	#  `mods-enabled/eap_inner`.
	#
	fast {
		#
		#  tls::  Point to the common TLS configuration
		#
		tls = tls-common

		#
		#  cipher_list:: Set the list of allowed TLS cipher suites.
		#
		#  If `cipher_list` is set here, it will override the
		#  `cipher_list` configuration from the `tls-common`
		#  configuration.  The `EAP-FAST` module has its own override
		#  for `cipher_list` because the specifications mandate a
		#  different set of ciphers than are used by the other `EAP`
		#  methods.
		#
		#  The `cipher_list` MUST include "ADH" for anonymous
		#  provisioning.  This is not as straightforward as appending
		#  "ADH" alongside "DEFAULT" as "DEFAULT" contains "!aNULL" so
		#  instead it is recommended "ALL:!EXPORT:!eNULL:!SSLv2" is used
		#
		#  NOTE: for OpenSSL 1.1.0 and above you may need to add ":@SECLEVEL=0"
		#
		cipher_list = "ALL:!EXPORT:!eNULL:!SSLv2"

		#
		#  pac_lifetime:: PAC lifetime in seconds.
		#
		#  Default is: `seven days`
		#
		pac_lifetime = 604800

		#
		#  authority_identity:: Authority ID of the server.
		#
		#  if you are running a cluster of RADIUS servers, you should make
		#  the value chosen here (and for `pac_opaque_key`) the same on all
		#  your RADIUS servers.  This value should be unique to your
		#  installation.  We suggest using a domain name.
		#
		authority_identity = "1234"

		#
		#  pac_opaque_key:: Key sued to encrypt the PAC.
		#
		#  The PAC key must be exactly 32 bytes in size.
		#
		#  This value MUST be secret, and MUST be generated using
		#  a secure method, such as via `openssl rand -hex 32`
		#
		pac_opaque_key = "0123456789abcdef0123456789ABCDEF"

		#
		#  virtual_server:: The virtual server used for "inner" authentication.
		#
		virtual_server = inner-tunnel

		#
		#  default_provisioning_eap_type:: Default provisioning EAP type.
		#
		#  Default is `mschapv2`
		#
#		default_provisioning_eap_type = mschapv2
	}

	#
	#  ### EAP-SIM
	#
	sim {
		#
		#  virtual_server:: The EAP-SIM virtual server containing policy
		#  sections.
		#
		#  This configuration must be set, EAP-SIM will not function
		#  without it, as certain operations such as getting SIM vectors
		#  require configuration for each user.
		#
		virtual_server = eap-aka-sim
	}

	#
	#  ### EAP-AKA
	#
	aka {
		#
		#  prefer_aka_prime:: Send the AT_BIDDING attribute in
		#  AKA-Challenge messages.
		#
		#  When AT_BIDDING is sent in a AKA-Challenge and the supplicant
		#  supports EAP-AKA-Prime, RFC 5448 states the supplicant
		#  should abort the authentication attempt as a bidding down
		#  attack may have occurred.
		#
		#  If a value is not provided for this configuration item
		#  it will be determined automatically by whether the
		#  EAP-AKA-Prime EAP method is enabled.
		#
#		prefer_aka_prime = yes

		#
		#  virtual_server:: The EAP-SIM virtual server containing policy
		#  sections.
		#
		#  This configuration must be set, EAP-AKA will not function
		#  without it, as certain operations such as getting vectors
		#  require configuration for each user.
		#
		virtual_server = eap-aka-sim
	}

	#
	#  ### EAP-AKA-Prime
	#
	aka-prime {
		#
		#  virtual_server:: The EAP-SIM virtual server containing policy
		#  sections.
		#
		#  This configuration must be set, EAP-AKA' will not function
		#  without it, as certain operations such as getting vectors
		#  require configuration for each user.
		#
		virtual_server = eap-aka-sim
	}
}

#
#  ## Expansions
#
#  The rlm_eap module provides the below functions to interact with the `3GPP` and `SIM` protocols.
#
#  ### %3gpp_temporary_id_decrypt('...)
#
#  TODO
#
#  .Return: _string_
#
#  .Example
#
#  [source,unlang]
#  ----
#  TODO
#  ----
#
#  .Output
#
#  ```
#  TODO
#  ```
#
#  ### %3gpp_temporary_id_encrypt(...)
#
#  TODO
#
#  .Return: _string_
#
#  .Example
#
#  [source,unlang]
#  ----
#  TODO
#  ----
#
#  .Output
#
#  ```
#  TODO
#  ```
#
#  ### %3gpp_temporary_id_key_index(...)
#
#  TODO
#
#  .Return: _string_
#
#  .Example
#
#  [source,unlang]
#  ----
#  TODO
#  ----
#
#  .Output
#
#  ```
#  TODO
#  ```
#
#  ### %aka_sim_id_method(...)
#
#  TODO
#
#  .Return: _string_
#
#  .Example
#
#  [source,unlang]
#  ----
#  TODO
#  ----
#
#  .Output
#
#  ```
#  TODO
#  ```
#
#  ### %aka_sim_id_type(...)
#
#  TODO
#
#  .Return: _string_
#
#  .Example
#
#  [source,unlang]
#  ----
#  TODO
#  ----
#
#  .Output
#
#  ```
#  TODO
#  ```
