logo_kerberos.gif

Difference between revisions of "Projects/Initial creds improvements"

From K5Wiki
Jump to: navigation, search
(Stage 3: Pre-authentication)
Line 1: Line 1:
 
{{project-early}}
 
{{project-early}}
   
This project is an internal improvement and should have minimal externally visible impact.
+
This project is mostly internal design changes to the initial creds API. The immediate user-visible impact should not be significant.
   
 
==Background==
 
==Background==
Line 7: Line 7:
 
get_in_tkt.c implements the krb5_init_creds_step() API, which is responsible for processing a KDC reply and generating the next request (or terminating the exchange). Currently this function is divided into two helper functions: init_creds_step_reply(), which examines the KDC reply and alters the request state, and init_creds_step_request(), which generates a request based on the current state.
 
get_in_tkt.c implements the krb5_init_creds_step() API, which is responsible for processing a KDC reply and generating the next request (or terminating the exchange). Currently this function is divided into two helper functions: init_creds_step_reply(), which examines the KDC reply and alters the request state, and init_creds_step_request(), which generates a request based on the current state.
   
Several conditions can cause a "restart" of the exchange, discarding any existing KDC padata and FAST state: a realm referral, a KDC_ERR_PREAUTH_FAILED response when the client sent only informational padata, or a PA-FX-FAST padata element when the client did not use FAST but has an armor key.
 
  +
The current code has the following limitations, most of which do not arise in current pre-authentication scenarios:
   
Although the krb5_init_creds_context structure contains many state variables, they do not track a progression towards the end goal. As a result, an attacker impersonating a KDC can send replies to the client in non-sensical orders, which the client will attempt to interpret. This project will add stage-tracking so that the client can better manage request state.
 
  +
* If two krb5_init_creds_step() operations are interleaved using the same krb5_context, they erroneously share per-request per-module data pointers, which may confuse clpreauth modules. (They also share the "tried" list which tracks previously tried mechanisms, but that list is not currently doing much.)
   
==Proposed stages==
 
  +
* Support for optimistic preauth is very limited. It must be initiated by the calling application, not by configuration, and there is no way to specify salt or s2kparams for producing the reply key.
   
===Stage 1: Optimistic pre-authentication===
 
  +
* If a preauth mechanism fails (even during optimistic preauth), we do not continue on to other mechanisms, unless it failed on the client side during method-data processing.
   
If no optimistic pre-authentication information is available, and the client moves immediately to stage 2. In the future, we may implement optimistic PA-SPAKE, in which case there will always be an optimistic pre-authentication step.
 
  +
* clpreauth modules do not get much information about the padata they are processing. It could be from optimistic preauth, from KDC METHOD-DATA in a PREAUTH_REQUIRED error, from KDC METHOD-DATA in a MORE_PREAUTH_DATA_REQUIRED error, or from an AS-REP. (Other KDC errors are handled via the tryagain method, so those are distinguishable.)
   
We currently have minimal support for optimistic pre-authentication: the caller can specify a list of preauth types with krb5_get_init_creds_opt_set_preauth_list() to activate those mechanisms for the initial request; any parameters needed by the preauth mechs must be determined via gic options or profile variables, none of which we currently have. Optimistic pre-authentication is currently performed after restarts, but this property is not important; in the proposed new plan, only one optimistically pre-authenticated request will be generated.
 
  +
* clpreauth modules cannot indicate that they expect additional padata values before the mechanism is complete. In the middle of a conversation, a KDC could issue an AS-REP with no padata and the client would try to decrypt it with whatever the reply key currently is. This limitation has no current security consequences, but could become important in the future.
   
If the KDC responds with KDC_ERR_PREAUTH_FAILED, the client should move to stage 3 if the error includes METHOD-DATA, or to stage 2 if it does not. If the KDC responds with KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, it should respond as in stage 3. Otherwise, the client should respond as in stage 2.
 
  +
* The preferred_preauth_types realm variable is a hack; the order of KDC padata should be the preferred order. However, it is important to keep trying PKINIT first by default as current KDCs do not always put it before encrypted timestamp when they ought to.
   
(XXX problem: if the KDC responds with PREAUTH_FAILED and a hint list, we should really move to stage 3, especially if we're doing optimistic PA-SPAKE all the time. But what if the KDC them comes back with a realm referral? The whole idea is not to backtrack stages. This needs more thought.)
 
  +
==Improvements==
   
===Stage 2: Unauthenticated request===
+
===Proper scoping of per-request preauth data===
   
In this stage, the client sends a request with no substantive padata and no cookie. It may send informational padata such as PA-REQ-ENC-PA-REP or PA-AS-FRESHNESS.
 
  +
The per-request krb5_clpreauth_modreq pointers for each module should be maintained an object separate from krb5_preauth_context. This object should be linked from krb5_init_creds_context.
   
If the KDC responds with a realm referral (KDC_ERR_WRONG_REALM or KDC_ERR_C_PRINCIPAL_UNKNOWN with a distinct crealm), the client should remain in stage 2 and retry in the new realm.
 
  +
The "tried" list is currently unused and should be removed. A list of preauthentication mechanisms which have failed should be maintained separately from preauth state.
   
If the KDC responds with KDC_ERR_PREAUTH_FAILED, it is likely a pre-1.7 MIT krb5 KDC which does not ignore unknown client padata types. The client should remain in stage 2 and retry without informational padata. This retry should not be performed twice without changing realms.
 
  +
===Optimistic preauth===
   
If the KDC responds with an error containing padata, one of the padata elements is PA-FX-FAST, and the client did not use FAST but has an armor key, the client should remain in stage 2 and should retry using FAST. This retry should be exclusive with the previous retry, as pre-1.7 MIT krb5 KDCs do not support FAST.
 
  +
TBD
   
If the KDC responds with KDC_ERR_PREAUTH_REQUIRED, the client should move to stage 3.
 
  +
==Continuing after failures===
   
If the KDC responds with any other error, the client should abort the exchange.
 
  +
A preauth mechanism can fail in several ways:
   
If the KDC responds with an AS-REP, the client should move to stage 4.
 
  +
* The clpreauth module's process method can fail to generate initial padata value during optimistic preauth or processing of KDC method-data. In this case we already continue on to the next mechanism.
   
===Stage 3: Pre-authentication===
 
  +
* The KDC can reply with KDC_ERR_PREAUTH_FAILED, with or without METHOD-DATA.
   
In this stage, the client sends a pre-authenticated request using the METHOD-DATA from a previous KDC error, which we will call the "current hint list." The client iterates over the current hint list in the order supplied by the KDC (perhaps as re-sorted by preferred_preauth_types) and selects the first non-informational pre-authentication mechanism for which it can produce a padata value. If no padata value can be generated, the client should abort the exchange.
 
  +
* The KDC can reply with KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, and the process method can fail to generate a padata value.
   
If the KDC responds with KDC_ERR_PREAUTH_REQUIRED, the client should remain in stage 3, replace the current hint list, and produce a new pre-authenticated message. This case should be unusual, the MIT KDC does it as part of the SAM-2 Duo integration. The client may restrict this case to the situation when the previous requested used SAM-2, and may restrict itself to using SAM-2 for subsequent requests, but it must be willing to perform multiple KDC_ERR_PREAUTH_REQUIRED -> PA-SAM-2 round trips.
 
  +
* The KDC can reply with another error containing e-data, and the tryagain method can fail to generate a padata value.
   
If the KDC responds with KDC_ERR_MORE_PREAUTH_REQUIRED, the client should remain in stage 3 and continue using the same pre-authentication mechanism, passing the padata for that type to the mechanism's handler to produce a new padata value. If the clpreauth module cannot continue, the client should move on to the next untried padata type in the current hint list.
 
  +
If optimistic preauth results in KDC_ERR_PREAUTH_FAILED, we should discard per-request preauth state and begin anew. If the KDC included METHOD-DATA, we should use that; otherwise we should send an unauthenticated request in order to get a KDC_ERR_PREAUTH_REQUIRED error with METHOD-DATA.
   
If the KDC responds with KDC_ERR_PREAUTH_FAILED, the client should remain in stage 3 and try the next untried padata type in the current hint list.
 
  +
The first time we receive a KDC METHOD-DATA list, we should remember it for the purpose of continuing after failures. We should discard this list on a KDC_ERR_PREAUTH_EXPIRED error (as the METHOD-DATA list may include a stale cookie). If we receive multiple METHOD-DATA lists, we can either replace the initial list or ignore the subsequent lists; it should not be very important. However, the METHOD-DATA in a KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error should be treated separately from this list, as it is part of a multi-hop conversation for a particular mechanism.
   
If the KDC responds with KDC_ERR_PREAUTH_EXPIRED, the client should discard the current hint list and move back to stage 2. (This is the only case where stage back-tracking occurs. There is no way to avoid it, as any previously received hint list may include a cookie which is now expired.) If the AS key was generated during a previous attempt, it should be retained. Any responder items should also be retained.
 
  +
We should maintain a list of preauth mechanisms which have failed so that we don't try them again. This list should be separate from the KDC METHOD-DATA and the preauth request state, as we should not retry a failed preauth mechanism after KDC_ERR_PREAUTH_EXPIRED. This list should be discarded on a realm referral, although a realm referral during a preauthentication conversation should be rare. A KDC_ERR_PREAUTH_EXPIRED error should not count as failing. Optimistic preauthentication failure should not count either, as it may only have failed for lack of information from the KDC.
   
If the KDC responds with any other error containing padata, the client should remain in stage 3 and try to produce a new padata value using the current mechanism's tryagain method.
 
  +
===Stage tracking for clpreauth modules===
   
If the KDC responds with an AS-REP, the client should move to stage 4.
 
  +
TBD
   
===Stage 4: AS-REP processing===
 
  +
===clpreauth module control of conversation termination===
   
In this stage, the client processes the padata in the AS-REP, and either aborts or successfully terminates the exchange.
 
  +
TBD

Revision as of 14:34, 24 June 2015

This is an early stage project for MIT Kerberos. It is being fleshed out by its proponents. Feel free to help flesh out the details of this project. After the project is ready, it will be presented for review and approval.


This project is mostly internal design changes to the initial creds API. The immediate user-visible impact should not be significant.

Background

get_in_tkt.c implements the krb5_init_creds_step() API, which is responsible for processing a KDC reply and generating the next request (or terminating the exchange). Currently this function is divided into two helper functions: init_creds_step_reply(), which examines the KDC reply and alters the request state, and init_creds_step_request(), which generates a request based on the current state.

The current code has the following limitations, most of which do not arise in current pre-authentication scenarios:

  • If two krb5_init_creds_step() operations are interleaved using the same krb5_context, they erroneously share per-request per-module data pointers, which may confuse clpreauth modules. (They also share the "tried" list which tracks previously tried mechanisms, but that list is not currently doing much.)
  • Support for optimistic preauth is very limited. It must be initiated by the calling application, not by configuration, and there is no way to specify salt or s2kparams for producing the reply key.
  • If a preauth mechanism fails (even during optimistic preauth), we do not continue on to other mechanisms, unless it failed on the client side during method-data processing.
  • clpreauth modules do not get much information about the padata they are processing. It could be from optimistic preauth, from KDC METHOD-DATA in a PREAUTH_REQUIRED error, from KDC METHOD-DATA in a MORE_PREAUTH_DATA_REQUIRED error, or from an AS-REP. (Other KDC errors are handled via the tryagain method, so those are distinguishable.)
  • clpreauth modules cannot indicate that they expect additional padata values before the mechanism is complete. In the middle of a conversation, a KDC could issue an AS-REP with no padata and the client would try to decrypt it with whatever the reply key currently is. This limitation has no current security consequences, but could become important in the future.
  • The preferred_preauth_types realm variable is a hack; the order of KDC padata should be the preferred order. However, it is important to keep trying PKINIT first by default as current KDCs do not always put it before encrypted timestamp when they ought to.

Improvements

Proper scoping of per-request preauth data

The per-request krb5_clpreauth_modreq pointers for each module should be maintained an object separate from krb5_preauth_context. This object should be linked from krb5_init_creds_context.

The "tried" list is currently unused and should be removed. A list of preauthentication mechanisms which have failed should be maintained separately from preauth state.

Optimistic preauth

TBD

Continuing after failures=

A preauth mechanism can fail in several ways:

  • The clpreauth module's process method can fail to generate initial padata value during optimistic preauth or processing of KDC method-data. In this case we already continue on to the next mechanism.
  • The KDC can reply with KDC_ERR_PREAUTH_FAILED, with or without METHOD-DATA.
  • The KDC can reply with KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, and the process method can fail to generate a padata value.
  • The KDC can reply with another error containing e-data, and the tryagain method can fail to generate a padata value.

If optimistic preauth results in KDC_ERR_PREAUTH_FAILED, we should discard per-request preauth state and begin anew. If the KDC included METHOD-DATA, we should use that; otherwise we should send an unauthenticated request in order to get a KDC_ERR_PREAUTH_REQUIRED error with METHOD-DATA.

The first time we receive a KDC METHOD-DATA list, we should remember it for the purpose of continuing after failures. We should discard this list on a KDC_ERR_PREAUTH_EXPIRED error (as the METHOD-DATA list may include a stale cookie). If we receive multiple METHOD-DATA lists, we can either replace the initial list or ignore the subsequent lists; it should not be very important. However, the METHOD-DATA in a KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error should be treated separately from this list, as it is part of a multi-hop conversation for a particular mechanism.

We should maintain a list of preauth mechanisms which have failed so that we don't try them again. This list should be separate from the KDC METHOD-DATA and the preauth request state, as we should not retry a failed preauth mechanism after KDC_ERR_PREAUTH_EXPIRED. This list should be discarded on a realm referral, although a realm referral during a preauthentication conversation should be rare. A KDC_ERR_PREAUTH_EXPIRED error should not count as failing. Optimistic preauthentication failure should not count either, as it may only have failed for lack of information from the KDC.

Stage tracking for clpreauth modules

TBD

clpreauth module control of conversation termination

TBD