[krbdev.mit.edu #2131] bug in 1.3.1 krb5_get_init_creds_keytab()

Arlene Berry via RT rt-comment at krbdev.mit.edu
Fri Jan 16 19:26:40 EST 2004


I've found a bug in krb5 1.3.1 in function krb5_get_init_creds_keytab().
I'm using MS Active Directory for my KDC.  I created a service principal
account and I created a key table entry for it with a DEC-CBC-MD5 key type.
The AD account has a userAccountControl atribute which contains bit flags.
When the UF_USE_DES_KEY_ONLY bit is set, krb5_get_init_creds_keytab()
successfully gets a TGT using the key table entry.  When the bit is not set,
the function returns the error "Key table entry not found".  When I do the
same thing with 1.2.5 or 1.2.8, krb5_get_init_creds_keytab() gets a TGT no
matter how that bit is set.  The reason it's an issue is that if an AD
account is created with the bit set, a key table entry is created, and then
later someone changes the UF_USE_DES_KEY_ONLY bit, the key table entry can
no longer be used to get a TGT even though it's still good.

I've done a lot of debugging.  The basic sequence of events is that a
request is built without preauth and sent to the KDC, a reply requesting
preauth is received, and an attempt is made to satisfy the request for
preauth.  Krb5_get_init_creds_keytab() calls krb5_get_init_creds() which
calls krb5_do_preauth().  What happens in krb5_do_preauth() is that it looks
at a list of etypes returned by the KDC, chooses one, and then tries to find
a key table entry with a similar key type.  The code which chooses the etype
looks like this:

    for (etype_found = 0, valid_etype_found = 0, k = 0;
         !etype_found && k < request->nktypes; k++) {
        for (l = 0; etype_info[l]; l++) {
            if (etype_info[l]->etype == request->ktype[k]) {
                etype_found++;
                break;
            }

The etype_info array comes from the KDC's reply.  Request->ktype is provided
by krb5_get_init_creds().  Krb5_get_init_creds() creates request and sets
request->ktype to the results of krb5_get_default_in_tkt_ktypes() if not
overridden by the options parameter which is passed from the application to
krb5_get_init_creds() by krb5_get_init_creds_keytab().

With AD the etype_info[]->etype list of etypes is 3, 1 when
UF_USE_DES_KEY_ONLY is set and the list is 23, 3, 1 when UF_USE_DES_KEY_ONLY
is not set.  The list provided by krb5_get_default_in_tkt_ktypes() is 18,
16, 23, 1, 3, 2.  The type chosen is 1 when AD returns 3, 1 and it's 23 when
AD returns 23, 3, 1.  The problem is nothing looked in the key table to see
what's actually available.  The key table lookup happens after the type is
chosen.  Since what's in the key table is 3 which is similar to 1, the key
table entry is used when UF_USE_DES_KEY_ONLY is set, and it's rejected when
UF_USE_DES_KEY_ONLY is not set.

The 1.2.8 preauth code simply uses the first entry in the etype_info array
which is always 3 which must be because 1.2.8 doesn't support 23 and doesn't
include it in its initial request.

The real problem is that the default ktypes list that krb5_get_init_creds()
uses in the initial request is not suitable when krb5_get_init_creds() is
called by krb5_get_init_creds_keytab().  It seems to me that the solution is
for krb5_get_init_creds_keytab() to examine the key table and set an etype
list in the options parameter before passing it through to
krb5_get_init_creds() if a list is not provided by the calling application.
If this change were made to krb5_get_init_creds_keytab(), it should solve
the problem as I simulated it by temporarily modifying the application to
set the options etype list to 3, 1 and got a TGT.

Arlene Berry




More information about the krb5-bugs mailing list