{
krb5_kt_cursor cursor;
krb5_keytab_entry entry;
- krb5_enctype *p, *etypes = NULL;
- krb5_kvno max_kvno = 0;
+ krb5_enctype *p, *etypes = NULL, etype;
+ krb5_kvno max_kvno = 0, vno;
krb5_error_code ret;
+ krb5_boolean match;
size_t count = 0;
*etypes_out = NULL;
if (ret != 0)
return ret;
- for (;;) {
- ret = krb5_kt_next_entry(context, keytab, &entry, &cursor);
- if (ret == KRB5_KT_END)
- break;
- if (ret)
- goto cleanup;
+ while (!(ret = krb5_kt_next_entry(context, keytab, &entry, &cursor))) {
+ /* Extract what we need from the entry and free it. */
+ etype = entry.key.enctype;
+ vno = entry.vno;
+ match = krb5_principal_compare(context, entry.principal, client);
+ krb5_free_keytab_entry_contents(context, &entry);
- if (!krb5_c_valid_enctype(entry.key.enctype)) {
- krb5_free_keytab_entry_contents(context, &entry);
- continue;
- }
- if (!krb5_principal_compare(context, entry.principal, client)) {
- krb5_free_keytab_entry_contents(context, &entry);
+ /* Filter out old or non-matching entries and invalid enctypes. */
+ if (vno < max_kvno || !match || !krb5_c_valid_enctype(etype))
continue;
- }
- /* Make sure our list is for the highest kvno found for client. */
- if (entry.vno > max_kvno) {
+
+ /* Update max_kvno and reset the list if we find a newer kvno. */
+ if (vno > max_kvno) {
+ max_kvno = vno;
free(etypes);
etypes = NULL;
count = 0;
- max_kvno = entry.vno;
- } else if (entry.vno != max_kvno) {
- krb5_free_keytab_entry_contents(context, &entry);
- continue;
}
/* Leave room for the terminator and possibly a second entry. */
p = realloc(etypes, (count + 3) * sizeof(*etypes));
if (p == NULL) {
- krb5_free_keytab_entry_contents(context, &entry);
ret = ENOMEM;
goto cleanup;
}
etypes = p;
- etypes[count++] = entry.key.enctype;
+ etypes[count++] = etype;
/* All DES key types work with des-cbc-crc, which is more likely to be
* accepted by the KDC (since MIT KDCs refuse des-cbc-md5). */
- if (entry.key.enctype == ENCTYPE_DES_CBC_MD5 ||
- entry.key.enctype == ENCTYPE_DES_CBC_MD4)
+ if (etype == ENCTYPE_DES_CBC_MD5 || etype == ENCTYPE_DES_CBC_MD4)
etypes[count++] = ENCTYPE_DES_CBC_CRC;
etypes[count] = 0;
- krb5_free_keytab_entry_contents(context, &entry);
}
-
+ if (ret != KRB5_KT_END)
+ goto cleanup;
ret = 0;
+
*etypes_out = etypes;
etypes = NULL;
+
cleanup:
krb5_kt_end_seq_get(context, keytab, &cursor);
free(etypes);