logo_kerberos.gif

Difference between revisions of "Projects/OTPOverRADIUS"

From K5Wiki
Jump to: navigation, search
(Proposal)
 
(45 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Description ==
 
  +
{{project-rel|1.12}}
  +
  +
= Description =
 
In 1.11 KRB5 gained client side support for OTP Preauth (RFC 6560), but up until now there is no server side support in tree. Red Hat has created an out-of-tree solution ([https://fedorahosted.org/AuthHub AuthHub]), based upon a plugin model. But our experimenting with this approach has demonstrated:
 
In 1.11 KRB5 gained client side support for OTP Preauth (RFC 6560), but up until now there is no server side support in tree. Red Hat has created an out-of-tree solution ([https://fedorahosted.org/AuthHub AuthHub]), based upon a plugin model. But our experimenting with this approach has demonstrated:
 
# Access to vendor SDKs is non-trivial
 
# Access to vendor SDKs is non-trivial
 
# All vendors provide a RADIUS server for OTP validation
 
# All vendors provide a RADIUS server for OTP validation
   
== Proposal ==
+
= Proposal =
   
The KDC-side support for OTP should read configuration from a user string and forward token validation to an appropriate RADIUS server. This plugin will be called otp_radius.
+
The KDC-side support for OTP should read configuration and forward token validation to an appropriate RADIUS server. This plugin will be called '''otp'''. In addition to standard RADIUS, the '''otp''' plugin will support a non-standard RADIUS over Unix Socket (RoUS; inconceivable!) mode for handling local companion daemons.
   
=== User String ===
 
  +
== Token Type Configuration ==
The user string '''otp_radius''' would contain a JSON formatted object which roughly reflects PA-OTP-CHALLENGE and is a near-duplicate of KRB5_RESPONDER_QUESTION_OTP, but containing support for RADIUS configuration:
 
  +
=== krb5.conf or kdc.conf ===
  +
The configuration is defined as follows:
 
<code>
 
<code>
{
 
  +
[otp]
"service": <string>,
 
  +
<name> = {
"tokenInfo": [{
 
  +
server = <string>
"flags": <integer>,
 
  +
secret = <string>
"vendor": <string>,
 
  +
timeout = <integer>
"challenge": <base64string>,
 
  +
retries = <integer>
"length": <integer>,
 
  +
strip_realm = <boolean>
"format": <integer>,
 
  +
}
"tokenID": <base64string>,
 
"algID": <string>,
 
"servers": [{
 
"host": <string>,
 
"port": <integer>,
 
"secret": <string>,
 
"attributes": {
 
"value": <number_or_string>,
 
"custom": [[<number_or_string>, <string>], ...]
 
}
 
}, ...]
 
}, ...]
 
}
 
 
</code>
 
</code>
   
In the object above, all fields are optional. If tokenInfo or servers is not specified, '[{}]' is assumed. If a server object is missing any fields, the following defaults are assumed:
 
  +
{| class="wikitable" style="width: 100%"
* host: localhost
 
  +
! Name || Default Value || Format
* port: getservbyname("radius", "udp")
 
  +
|-
* secret: send password in cleartext
 
  +
| otp.<name>.server || $KDCDIR/<name>.socket || host, host:port or /path/to/unix.socket
* attributes: {}
 
  +
|-
  +
| otp.<name>.secret || N/A (RoUS mode) or '''secret''' MUST be specified! || /path/to/secret.file
  +
|-
  +
| otp.<name>.timeout || 5 || Integer (seconds)
  +
|-
  +
| otp.<name>.retries || 3 || Integer
  +
|-
  +
| otp.<name>.strip_realm || true || Boolean
  +
|}
   
RADIUS attributes may be specified by a string ONLY in the case of the attributes defined in RFC 2865. Otherwise, a number must be used. Support for custom dictionaries is NOT provided.
 
  +
All values are optional except '''secret''' when a non-RoUS '''server''' is specified.
   
=== Workflow ===
 
  +
'''NOTE:''' We only permit a single server to be defined because we are assuming that redundancy will be handled via DNS round-robin.
In the first pass (no PA-OTP-REQUEST present), a PA-OTP-CHALLENGE will be generated from the user string (using all fields present except servers).
 
   
Upon receipt of a PA-OTP-REQUEST, the KDC will attempt to match the PA-OTP-REQUEST with a tokenInfo from the user string. All matching tokenInfo objects will then be used as configuration for RADIUS validation, in the order they were specified, stopping after the first AccessAccept response is received. A round-robin approach will be used on the servers specified for load balancing.
 
  +
=== Default Token Type ===
  +
There is a reserved token type name: '''DEFAULT'''. If no '''DEFAULT''' token type configuration is defined, the following configuration will be used internally:
  +
<code>
  +
[otp]
  +
DEFAULT = {
  +
strip_realm = false
  +
}
  +
</code>
  +
  +
You can override this default token type configuration by defining your own token type configuration with the name of '''DEFAULT'''.
  +
  +
== Token Instance Configuration ==
  +
  +
Some portion of the '''otp''' plugin configuration is user specific. This value will be stored as the user string '''otp''' with the following JSON formatted array of token objects:
  +
<code>
  +
[{
  +
"type": <string>,
  +
"username": <string>
  +
}, ...]
  +
</code>
  +
  +
If '''type''' is not specified then it refers to the '''DEFAULT''' token type as defined above. The '''username''' field overrides the default User-Name attribute sent in the RADIUS packet.
  +
  +
All values above are optional. If the user string is an empty string or is an empty list, then a user string of "[{}]" will be assumed.
  +
  +
== OTP Enablement ==
  +
The '''otp''' plugin will be enabled for all principals which have the '''otp''' user string set, regardless of its value. Conversely, if the '''otp''' user string is unset, the '''otp''' plugin will be disabled for the principal.
  +
  +
== Workflow ==
  +
In the first pass (no PA-OTP-REQUEST present), the '''otp''' plugin will look up the '''otp''' user string on the given principal. If the string is set (i.e. non-NULL), a generic PA-OTP-CHALLENGE will be sent to the client (no optional fields will be filled in).
  +
  +
Upon receipt of a PA-OTP-REQUEST, the KDC will look up the RADIUS servers using the '''otp''' user string and kdc.conf configuration. All RADIUS servers will be used for validation, in the order they were specified in the '''otp''' user string, stopping after the first Access-Accept response is received.
   
 
=== RADIUS Packet ===
 
=== RADIUS Packet ===
The packet sent to the configured RADIUS server will first contain any attributes specified in the custom attributes configuration. However, any attempt to set the User-Password attribute in this field will be ignored. If a custom User-Name attribute is not specified in the server object, the KDC will then append two User-Name attributes containing the user's principal both with and without the realm. The otp-value of PA-OTP-REQUEST will be sent as a User-Password attribute. If the separate-pin-required flag is set in the flags field, the otp-pin of PA-OTP-REQUEST will be sent as an additional User-Password attribute OR as the attribute specified in the value attribute field.
 
  +
The packet sent to the configured RADIUS server will contain:
  +
* User-Name (default: user principal, realm stripped per config; overridden by '''username''')
  +
* User-Password (otp-value from PA-OTP-REQUEST)
  +
* NAS-Identifier (gethostname())
  +
* Service-Type (Authenticate-Only)
  +
  +
= Remaining Issues =
  +
== FIPS compliance ==
  +
We are not targeting FIPS compliance, but for those who are interested here is the related information:
  +
* RADIUS is not FIPS compliant due to the use of MD5 in the protocol
  +
* EAP might make RADIUS FIPS compliant and Fedora ships a libeap
  +
* Integration of EAP is not planned at this time
  +
== OTP Preauth Challenge Optional Fields ==
  +
According to RFC 6560, there are many optional fields. We currently do not have any plan to fill these in.
  +
  +
= Testing =
  +
  +
libkrad will be tested with C test programs located in lib/krad. Some of the programs will spawn a Python daemon which uses pyrad to provide a simple RADIUS server to test against.
  +
  +
The OTP module will be tested by a new script tests/t_otp.py, which also uses pyrad to provide a RADIUS server to test against.
  +
  +
= Documentation =
  +
  +
A new page admin/otp.rst will describe KDC configuration for OTP.
  +
  +
= Mailing list discussions =
  +
  +
* http://mailman.mit.edu/pipermail/krbdev/2012-December/011300.html
  +
* http://mailman.mit.edu/pipermail/krbdev/2013-May/011528.html
  +
  +
= Commits =
  +
  +
8b8f031c6e64360a26c484b548d2158944e09087 Add libkrad
  +
4b5dd8bcfb10af254fb9efbe4cf39befe5b1e6ac Add server-side otp preauth plugin
  +
f6cb089daed2615d0b1594d7ccc20d617eb374eb Fix skip logic in t_otp.py
  +
acb490bd01235511294ecb6b23750e648e48f7dc Fix OTP KDC module get_string error handling
  +
  +
Completed in {{bug|7678}}.
  +
  +
= Release notes =
  +
  +
Administrator experience:
   
=== Remaining Issues ===
 
  +
* Add a FAST OTP preauthentication module for the KDC which uses RADIUS to validate OTP token values.
* Should we use a RADIUS library or hand-craft packets?
 

Latest revision as of 13:26, 11 October 2013

This project was completed in release 1.12.


Description

In 1.11 KRB5 gained client side support for OTP Preauth (RFC 6560), but up until now there is no server side support in tree. Red Hat has created an out-of-tree solution (AuthHub), based upon a plugin model. But our experimenting with this approach has demonstrated:

  1. Access to vendor SDKs is non-trivial
  2. All vendors provide a RADIUS server for OTP validation

Proposal

The KDC-side support for OTP should read configuration and forward token validation to an appropriate RADIUS server. This plugin will be called otp. In addition to standard RADIUS, the otp plugin will support a non-standard RADIUS over Unix Socket (RoUS; inconceivable!) mode for handling local companion daemons.

Token Type Configuration

krb5.conf or kdc.conf

The configuration is defined as follows:

[otp]
 <name> = {
  server = <string>
  secret = <string>
  timeout = <integer>
  retries = <integer>
  strip_realm = <boolean>
 }

Name Default Value Format
otp.<name>.server $KDCDIR/<name>.socket host, host:port or /path/to/unix.socket
otp.<name>.secret N/A (RoUS mode) or secret MUST be specified! /path/to/secret.file
otp.<name>.timeout 5 Integer (seconds)
otp.<name>.retries 3 Integer
otp.<name>.strip_realm true Boolean

All values are optional except secret when a non-RoUS server is specified.

NOTE: We only permit a single server to be defined because we are assuming that redundancy will be handled via DNS round-robin.

Default Token Type

There is a reserved token type name: DEFAULT. If no DEFAULT token type configuration is defined, the following configuration will be used internally:

[otp]
 DEFAULT = {
  strip_realm = false
 }

You can override this default token type configuration by defining your own token type configuration with the name of DEFAULT.

Token Instance Configuration

Some portion of the otp plugin configuration is user specific. This value will be stored as the user string otp with the following JSON formatted array of token objects:

[{
   "type": <string>,
   "username": <string>
 }, ...]

If type is not specified then it refers to the DEFAULT token type as defined above. The username field overrides the default User-Name attribute sent in the RADIUS packet.

All values above are optional. If the user string is an empty string or is an empty list, then a user string of "[{}]" will be assumed.

OTP Enablement

The otp plugin will be enabled for all principals which have the otp user string set, regardless of its value. Conversely, if the otp user string is unset, the otp plugin will be disabled for the principal.

Workflow

In the first pass (no PA-OTP-REQUEST present), the otp plugin will look up the otp user string on the given principal. If the string is set (i.e. non-NULL), a generic PA-OTP-CHALLENGE will be sent to the client (no optional fields will be filled in).

Upon receipt of a PA-OTP-REQUEST, the KDC will look up the RADIUS servers using the otp user string and kdc.conf configuration. All RADIUS servers will be used for validation, in the order they were specified in the otp user string, stopping after the first Access-Accept response is received.

RADIUS Packet

The packet sent to the configured RADIUS server will contain:

  • User-Name (default: user principal, realm stripped per config; overridden by username)
  • User-Password (otp-value from PA-OTP-REQUEST)
  • NAS-Identifier (gethostname())
  • Service-Type (Authenticate-Only)

Remaining Issues

FIPS compliance

We are not targeting FIPS compliance, but for those who are interested here is the related information:

  • RADIUS is not FIPS compliant due to the use of MD5 in the protocol
  • EAP might make RADIUS FIPS compliant and Fedora ships a libeap
  • Integration of EAP is not planned at this time

OTP Preauth Challenge Optional Fields

According to RFC 6560, there are many optional fields. We currently do not have any plan to fill these in.

Testing

libkrad will be tested with C test programs located in lib/krad. Some of the programs will spawn a Python daemon which uses pyrad to provide a simple RADIUS server to test against.

The OTP module will be tested by a new script tests/t_otp.py, which also uses pyrad to provide a RADIUS server to test against.

Documentation

A new page admin/otp.rst will describe KDC configuration for OTP.

Mailing list discussions

Commits

   8b8f031c6e64360a26c484b548d2158944e09087 Add libkrad
   4b5dd8bcfb10af254fb9efbe4cf39befe5b1e6ac Add server-side otp preauth plugin
   f6cb089daed2615d0b1594d7ccc20d617eb374eb Fix skip logic in t_otp.py
   acb490bd01235511294ecb6b23750e648e48f7dc Fix OTP KDC module get_string error handling

Completed in [krbdev.mit.edu #7678].

Release notes

Administrator experience:

  • Add a FAST OTP preauthentication module for the KDC which uses RADIUS to validate OTP token values.