#  -*- text -*-
#
#
#  $Id: 48da2a890a8239958ba23034850a6d599ccff322 $

#######################################################################
#
#  = Yubikey Module
#
#  The `yubikey` module decrypts and validates Yubikey static and
#  dynamic One-Time Password (OTP) tokens.
#
#  For more information about Yubikey, please see:
#
#	https://www.yubico.com/
#

#
#  ## Configuration Settings
#
yubikey {
	#
	#  id_length:: The length (number of ASCII bytes) of the Public-ID portion
	#  of the OTP string.
	#
	#  Yubikey defaults to a 6 byte ID (2 * 6 = 12)
	#
#	id_length = 12

	#
	#  split:: If true, the authorize method of `rlm_yubikey` will attempt to split the
	#  value of `User-Password`, into the user's password, and the OTP token.
	#
	#  NOTE: If enabled and successful, the value of `&request.User-Password` will be
	#  truncated and `&request.Vendor-Specific.Yubicon.Yubikey-OTP` will be added.
	#
#	split = yes

	#
	#  decrypt:: Whether tokens will be decrypted and processed locally.
	#
	#  In the `authorize` section, this module should be placed before the
	#  persistent storage module.
	#
	#  The authenticate section should have the following added:
	#
	#  [source,unlang]
	#  ----
	#  Auth-Type yubikey {
	#    #pap
	#    yubikey
	#  }
	#  ----
	#
	#  If two factor authentication (password concatenated with OTP) is required, split
	#  configuration should be set to yes and the pap module should be uncommented.
	#
	#  Each account will need a password added (either using attribute `Password.Cleartext`,
	#  `SSHA-Password`, etc.).
	#
	#  The module itself does not provide persistent storage as
	#  this would duplicate functionality already in the server.
	#
	#  Yubikey authentication needs two attributes retrieved from persistent storage:
	#
	#  [options="header,autowidth"]
	#  |===
	#  | Attributes                                         | Description
	#  | `&control.Vendor-Specific.Yubicon.Yubikey-Key`     | The AES key used to decrypt the OTP data.
	#                                                         The `Yubikey-Public-Id` and/or User-Name
	#                                                         attributes may be used to retrieve the key.
	#                                                         The value is a `16-byte` binary blob.
	#  | `&control.Vendor-Specific.Yubicon.Yubikey-Counter` | This is compared with the counter in the OTP
	#                                                         data and used to prevent replay attacks.
	#                                                         This attribute will also be available in
	#                                                         the request list after successful decryption.
	#  |===
	#
	#  NOTE: `Vendor-Specific.Yubicon.Yubikey-Counter` isn't strictly required, but the server will generate
	#  warnings if it's not present when `yubikey.authenticate` is called.
	#
	#  These attributes are available after `authorization`:
	#
	#  [options="header,autowidth"]
	#  |===
	#  | Attributes                                           | Description
	#  | `&request.Vendor-Specific.Yubicon.Yubikey-Public-ID` | The public portion of the OTP string.
	#                                                           The value is a `id_len` modhex string.
	#  |===
	#
	#  and additionally if 'split' is set:
	#
	#  [options="header,autowidth"]
	#  |===
	#  | Attributes                                     | Description
	#  | `&request.Vendor-Specific.Yubicon.Yubikey-OTP` | The OTP portion of `User-Password`.
	#  |===
	#
	#  These attributes are available after authentication (if successful):
	#
	#  [options="header,autowidth"]
	#  |===
	#  | Attributes                                            | Description
	#  | `&request.Vendor-Specific.Yubicon.Yubikey-Private-ID` | The encrypted ID included in OTP data,
	#                                                            should be verified for increased security.
	#                                                            The value is a `6-byte` binary blob.
	#  | `&request.Vendor-Specific.Yubicon.Yubikey-Counter`    | The last counter value (should be recorded).
	#                                                            The value is a concatenation of the 16-bit
	#                                                            session count & `8-bit` use count which form a
	#                                                            `24-bit` monotonically strictly increasing
	#                                                            integer (until the individual count ceilings
	#                                                            are hit)
	#  | `&request.Vendor-Specific.Yubicon.Yubikey-Timestamp`  | Token's internal clock (mainly useful for debugging).
	#                                                            The value is a 24-bit increasing `integer @ 8 Hz`
	#                                                            with rollover which is randomly initialized each session.
	#  | `&request.Vendor-Specific.Yubicon.Yubikey-Random`     | Randomly generated value from the token.
	#                                                            The value is a 16-bit integer.
	#  |===
	#
	decrypt = no

	#
	#  validate:: Validation mode - Tokens will be validated against a Yubicloud server.
	#
	validate = no

	#
	#  validation { ... }::
	#
	#  Settings for validation mode.
	#
	validation {
		#
		#  servers { ... }::
		#
		#  URL of validation server, multiple URL config items may be used
		#  to list multiple servers.
		#
		#  [options="header,autowidth"]
		#  |===
		#  | Option | Description
		#  | `%d`   | Placeholder for public ID of the token.
		#  | `%s`   | Placeholder for the token string itself.
		#  |===
		#
		#  NOTE: If no URLs are listed, will default to the default URLs in the
		#  ykclient library, which point to the yubico validation servers.
		#
		servers {
#			uri = 'http://api.yubico.com/wsapi/2.0/verify?id=%d&otp=%s'
#			uri = 'http://api2.yubico.com/wsapi/2.0/verify?id=%d&otp=%s'
		}

		#
		#  client_id:: API Client ID.
		#
		#  Must be set to your client id for the validation server.
		#
#		client_id = 00000

		#
		#  api_key:: API Secret key (Base64 encoded).
		#
		#  Must be set to your API key for the validation server.
		#
#		api_key = '000000000000000000000000'

		#
		#  pool { ... }:: Connection pool parameters.
		#
		pool {
			#
			#  start:: Connections to create during module instantiation.
			#
			#  If the server cannot create specified number of
			#  connections during instantiation it will exit.
			#  Set to `0` to allow the server to start without the
			#  external service being available.
			#
			start = 0

			#
			#  min:: Minimum number of connections to keep open.
			#
			min = 0

			#
			#  max:: Maximum number of connections.
			#
			#  If these connections are all in use and a new one
			#  is requested, the request will NOT get a connection.
			#
			#  Setting `max` to *LESS* than the number of threads means
			#  that some threads may starve, and you will see errors
			#  like _No connections available and at max connection limit_.
			#
			#  Setting `max` to MORE than the number of threads means
			#  that there are more connections than necessary.
			#
			#  If `max` is not specified, then it defaults to the number
			#  of workers configured.
			#
#			max =
			#
			#  uses:: Number of uses before the connection is closed.
			#
			#  NOTE: A setting of 0 means infinite (no limit).
			#
			uses = 0

			#
			#  retry_delay:: The number of seconds to wait after the server tries
			#  to open a connection, and fails.
			#
			#  During this time, no new connections will be opened.
			#
			retry_delay = 30

			#
			#  lifetime:: The lifetime (in seconds) of the connection.
			#
			#  NOTE: A setting of 0 means infinite (no limit).
			#
			lifetime = 86400

			#
			#  idle_timeout:: The idle timeout (in seconds).
			#
			#  A connection which is unused for this length of time will be closed.
			#
			#  NOTE: A setting of 0 means infinite (no timeout).
			#
			idle_timeout = 60

			#
			#  spread:: Enable LRU (Least Recently Used).
			#
			#  The `yubico` library uses `curl` multi-handles. If the multi-handle is reused
			#  before all requests are completed the connections are re-established.
			#
			#  The cost of re-establishing the connections is greater than the benefit of
			#  maintaining a small pool of connections or optimising for link latency.
			#
			spread = yes

			#
			#  [NOTE]
			#  ====
			#  All configuration settings are enforced.  If a connection is closed because of
			#  `idle_timeout`, `uses`, or `lifetime`, then the total
			#  number of connections MAY fall below `min`.
			#
			#  When that happens, it will open a new connection. It will also log a *WARNING* message.
			#
			#  The solution is to either lower the "min" connections, or
			#  increase lifetime/idle_timeout.
			#  ====
			#
		}
	}
}

#
#  ## Expansions
#
#  The rlm_yubikey provides the below xlat's functions.
#
#  ### %modhextohex(...)
#
#  Convert Yubikey modhex to standard hex.
#
#  .Return: _string_
#
#  .Example
#
#  [source,unlang]
#  ----
#  "%modhextohex(vvrbuctetdhc)" == "ffc1e0d3d260"
#  ----
#
#  .Output
#
#  ```
#  TODO
#  ```
#
