Difference between revisions of "Projects/OTPOverRADIUS"
Npmccallum (talk | contribs) (→Workflow) |
Npmccallum (talk | contribs) |
||
Line 8: | Line 8: | ||
= Proposal = |
= 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'''. |
+ | 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 additional to standard RADIUS, the '''otp''' plugin will support a non-standard RADIUS over Unix Socket (RoUS; inconceivable!) mode for handling local companion daemons. |
− | |||
− | === Configuration === |
||
+ | == Token Type Configuration == |
||
+ | === kdc.conf === |
||
Configuration should go into kdc.conf as it may contain secrets that shouldn't be world readable. The configuration is defined as follows: |
Configuration should go into kdc.conf as it may contain secrets that shouldn't be world readable. The configuration is defined as follows: |
||
<code> |
<code> |
||
Line 21: | Line 23: | ||
remote = <string> |
remote = <string> |
||
secret = <string> |
secret = <string> |
||
− | + | stripRealm = <boolean> |
|
attributes = { |
attributes = { |
||
<name> = <string> |
<name> = <string> |
||
Line 29: | Line 31: | ||
</code> |
</code> |
||
− | The follow values are informational only and will be sent to the client only if set in the config. |
||
+ | {| class="wikitable" style="width: 100%" |
||
− | * vendor |
||
+ | ! Name || Sent to Client || Default Value || Format |
||
− | * length |
||
+ | |- |
||
− | * format |
||
+ | | otp.<name>.vendor || yes || not sent || UTF8 String |
||
− | * algID |
||
+ | |- |
||
+ | | otp.<name>.length || yes || not sent || Integer |
||
+ | |- |
||
+ | | otp.<name>.format || yes || not sent || Enumeration: decimal, hexadecimal, alphanumeric, binary or base64 |
||
+ | |- |
||
+ | | otp.<name>.algID || yes || not sent || UTF8 URI |
||
+ | |- |
||
+ | | otp.<name>.server.remote || no || $KDCDIR/otp.socket OR $KDCDIR/<name>.socket* || host, host:port or /path/to/unix.socket |
||
+ | |- |
||
+ | | otp.<name>.server.secret || no || "" OR localhost:getservbyname("radius", "udp")** || String |
||
+ | |- |
||
+ | | otp.<name>.server.stripRealm || no || false || Boolean |
||
+ | |- |
||
+ | | otp.<name>.server.attributes || no || no additional attributes sent || <attrName> = <attrValue> |
||
+ | |} |
||
+ | {| |
||
+ | |* |
||
+ | |If no token types are defined, we'll use a generic name. Otherwise, we use the name of the token type. |
||
+ | |- |
||
+ | |** |
||
+ | |If '''remote''' indicates RoUS mode, an empty string is default. Otherwise, something like localhost:1812. |
||
+ | |} |
||
− | Server configuration is a little more complicated. If no token types are defined in the configuration and a user is configured for OTP access (see below), the otp plugin will fall back to a non-standard RADIUS-over-UNIX-Socket (RoUS; inconceivable!): $KDCDIR/otp.socket. If at least one token type is defined, any token type that does not implement the server section will fall back to RoUS, but with the name of the tokenType: $KDCDIR/<name>.socket. |
||
+ | === Default Token Type === |
||
− | |||
+ | If no token types are defined in the configuration, internally '''otp''' will define a default token type like this: |
||
− | If a server section is defined, it MUST contain the secret field or the token type will be ignored. This is to prevent insecure message passing in non-RoUS mode. All of the other values are optional, with the following defaults: |
||
+ | <code> |
||
− | * remote: localhost:getservbyname("radius", "udp") |
||
+ | [otp] |
||
− | * striprealm: false |
||
+ | <NO NAME> = { |
||
− | * attributes: none |
||
+ | server = { |
||
+ | remote = $KDCDIR/otp.socket |
||
+ | } |
||
+ | } |
||
+ | </code> |
||
− | The remote field can contain the following formats: |
||
+ | However, if one or more token types are defined in the configuration, the first valid configuration defined will be considered the default token type. |
||
− | * host |
||
− | * host:port |
||
− | * /path/to/unix/socket |
||
− | === User String === |
||
+ | == 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 |
+ | 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> |
<code> |
||
[{ |
[{ |
||
Line 58: | Line 82: | ||
</code> |
</code> |
||
− | All values above are optional. If '''type''' is not specified, the following will occur: |
||
+ | If '''type''' is not specified then it refers to the default token type as defined above. The '''id''' field identifies the unique id of the token and is sent in the PA-OTP-CHALLENGE. The '''username''' field overrides the default User-Name attribute sent in the RADIUS packet. |
||
− | * If no token types are defined in the config, we fall back to RoUS mode with the default socket. |
||
+ | |||
− | * If one or more token type is specified, the first one with valid configuration will be chosen. |
||
+ | All values above are optional. If the user string is not set (i.e. NULL) or is an empty string or is an empty list, then a user string of "[{}]" will be assumed. |
||
+ | |||
+ | == Flag == |
||
+ | The '''REQUIRES_HW_AUTH''' flag will indicate whether or not the '''otp''' plugin is enabled for a principal. |
||
− | + | == Workflow == |
|
− | In the first pass (no PA-OTP-REQUEST present), |
+ | In the first pass (no PA-OTP-REQUEST present), the '''otp''' plugin will look up the '''REQUIRES_HW_AUTH''' flag on the given principal. If not set, no PA-OTP-CHALLENGE will be generated. Otherwise we will look up the '''otp''' user string and a PA-OTP-CHALLENGE will be generated and sent to the client. |
− | Upon receipt of a PA-OTP-REQUEST, the KDC will attempt to match the PA-OTP-REQUEST with a |
+ | Upon receipt of a PA-OTP-REQUEST, the KDC will attempt to match the PA-OTP-REQUEST with a token type using the '''otp''' user string and kdc.conf configuration. All matches will then be used as configuration for RADIUS validation, in the order they were specified in the '''otp''' user string, stopping after the first AccessAccept response is received. |
=== RADIUS Packet === |
=== RADIUS Packet === |
||
Line 75: | Line 102: | ||
* Any custom attributes defined |
* Any custom attributes defined |
||
− | Any of the attributes specified above may be overridden by |
+ | Any of the attributes specified above may be overridden by the '''attributes''' section of the config except User-Name and User-Password. |
=== Remaining Issues === |
=== Remaining Issues === |
||
− | * Should we use a RADIUS library or hand-craft packets? We should use a RADIUS library which provides support for EAP methods. Unfortunately no such libraries exist. |
||
+ | * FIPS compliance |
||
− | * |
+ | * RADIUS is not FIPS compliant due to MD5 |
+ | * EAP might make RADIUS FIPS compliant and Fedora ships a libeap |
||
+ | * Integration of EAP is not planned at this time |
Revision as of 16:42, 5 December 2012
Contents
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:
- Access to vendor SDKs is non-trivial
- 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 additional 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
kdc.conf
Configuration should go into kdc.conf as it may contain secrets that shouldn't be world readable. The configuration is defined as follows:
[otp] <name> = { vendor = <string> length = <integer> format = <enum: decimal|hexadecimal|alphanumeric|binary|base64> algID = <string> server = { remote = <string> secret = <string> stripRealm = <boolean> attributes = { <name> = <string> } } }
Name | Sent to Client | Default Value | Format |
---|---|---|---|
otp.<name>.vendor | yes | not sent | UTF8 String |
otp.<name>.length | yes | not sent | Integer |
otp.<name>.format | yes | not sent | Enumeration: decimal, hexadecimal, alphanumeric, binary or base64 |
otp.<name>.algID | yes | not sent | UTF8 URI |
otp.<name>.server.remote | no | $KDCDIR/otp.socket OR $KDCDIR/<name>.socket* | host, host:port or /path/to/unix.socket |
otp.<name>.server.secret | no | "" OR localhost:getservbyname("radius", "udp")** | String |
otp.<name>.server.stripRealm | no | false | Boolean |
otp.<name>.server.attributes | no | no additional attributes sent | <attrName> = <attrValue> |
* | If no token types are defined, we'll use a generic name. Otherwise, we use the name of the token type. |
** | If remote indicates RoUS mode, an empty string is default. Otherwise, something like localhost:1812. |
Default Token Type
If no token types are defined in the configuration, internally otp will define a default token type like this:
[otp] <NO NAME> = { server = { remote = $KDCDIR/otp.socket } }
However, if one or more token types are defined in the configuration, the first valid configuration defined will be considered the default token type.
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>, "id": <string>, "username": <string> }, ...]
If type is not specified then it refers to the default token type as defined above. The id field identifies the unique id of the token and is sent in the PA-OTP-CHALLENGE. The username field overrides the default User-Name attribute sent in the RADIUS packet.
All values above are optional. If the user string is not set (i.e. NULL) or is an empty string or is an empty list, then a user string of "[{}]" will be assumed.
Flag
The REQUIRES_HW_AUTH flag will indicate whether or not the otp plugin is enabled for a principal.
Workflow
In the first pass (no PA-OTP-REQUEST present), the otp plugin will look up the REQUIRES_HW_AUTH flag on the given principal. If not set, no PA-OTP-CHALLENGE will be generated. Otherwise we will look up the otp user string and a PA-OTP-CHALLENGE will be generated and sent to the client.
Upon receipt of a PA-OTP-REQUEST, the KDC will attempt to match the PA-OTP-REQUEST with a token type using the otp user string and kdc.conf configuration. All matches will then be used as configuration for RADIUS validation, in the order they were specified in the otp user string, stopping after the first AccessAccept response is received.
RADIUS Packet
The packet sent to the configured RADIUS server will contain:
- User-Name (default: user principal; realm stripped per config)
- User-Password (otp-value from PA-OTP-REQUEST)
- NAS-Identifier (default: gethostname())
- Service-Type (default: Authenticate-Only)
- Any custom attributes defined
Any of the attributes specified above may be overridden by the attributes section of the config except User-Name and User-Password.
Remaining Issues
- FIPS compliance
* RADIUS is not FIPS compliant due to MD5 * EAP might make RADIUS FIPS compliant and Fedora ships a libeap * Integration of EAP is not planned at this time