#include <k5-int.h>
#ifndef LEAN_CLIENT
static krb5_error_code
decrypt_ticket_keyblock(krb5_context context, const krb5_keyblock *key,
krb5_ticket *ticket)
{
krb5_error_code retval;
krb5_data *realm;
krb5_transited *trans;
retval = krb5_decrypt_tkt_part(context, key, ticket);
if (retval)
goto done;
trans = &ticket->enc_part2->transited;
realm = &ticket->enc_part2->client->realm;
if (trans->tr_contents.data && *trans->tr_contents.data) {
retval = krb5_check_transited_list(context, &trans->tr_contents,
realm, &ticket->server->realm);
goto done;
}
if (ticket->enc_part2->flags & TKT_FLG_INVALID) {
retval = KRB5KRB_AP_ERR_TKT_INVALID;
goto done;
}
done:
return retval;
}
krb5_error_code KRB5_CALLCONV
krb5_server_decrypt_ticket_keytab(krb5_context context,
const krb5_keytab keytab,
krb5_ticket *ticket)
{
krb5_error_code retval;
krb5_keytab_entry ktent;
if (keytab->ops->start_seq_get == NULL) {
retval = krb5_kt_get_entry(context, keytab,
ticket->server,
ticket->enc_part.kvno,
ticket->enc_part.enctype, &ktent);
if (retval == 0) {
retval = decrypt_ticket_keyblock(context, &ktent.key, ticket);
(void) krb5_free_keytab_entry_contents(context, &ktent);
}
} else {
krb5_error_code code;
krb5_kt_cursor cursor;
retval = krb5_kt_start_seq_get(context, keytab, &cursor);
if (retval != 0)
goto map_error;
retval = KRB5_KT_NOTFOUND;
while ((code = krb5_kt_next_entry(context, keytab,
&ktent, &cursor)) == 0) {
if (ktent.key.enctype != ticket->enc_part.enctype) {
(void) krb5_free_keytab_entry_contents(context, &ktent);
continue;
}
retval = decrypt_ticket_keyblock(context, &ktent.key, ticket);
if (retval == 0) {
krb5_principal tmp;
retval = krb5_copy_principal(context, ktent.principal, &tmp);
if (retval == 0) {
krb5_free_principal(context, ticket->server);
ticket->server = tmp;
}
(void) krb5_free_keytab_entry_contents(context, &ktent);
break;
}
(void) krb5_free_keytab_entry_contents(context, &ktent);
}
code = krb5_kt_end_seq_get(context, keytab, &cursor);
if (code != 0)
retval = code;
}
map_error:
switch (retval) {
case KRB5_KT_KVNONOTFOUND:
case KRB5_KT_NOTFOUND:
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
retval = KRB5KRB_AP_WRONG_PRINC;
break;
default:
break;
}
return retval;
}
#endif