[krb5] backport a fix for keytabs which don't have keys for all enctypes
Nalin Dahyabhai
nalin at fedoraproject.org
Fri Jun 1 19:25:20 UTC 2012
commit 037ab925da1c65689107b5ccaf09c1e60ec3ed82
Author: Nalin Dahyabhai <nalin at dahyabhai.net>
Date: Fri Jun 1 15:24:41 2012 -0400
backport a fix for keytabs which don't have keys for all enctypes
- add a backport of Stef's patch to set the client's list of supported
enctypes to match the types of keys that we have when we are using a
keytab to try to get initial credentials, so that a KDC won't send us
an AS reply that we can't encrypt (RT#2131, #748528)
krb5-1.10.2-keytab-etype.patch | 332 ++++++++++++++++++++++++++++++++++++++++
krb5.spec | 6 +
2 files changed, 338 insertions(+), 0 deletions(-)
---
diff --git a/krb5-1.10.2-keytab-etype.patch b/krb5-1.10.2-keytab-etype.patch
new file mode 100644
index 0000000..4750a5c
--- /dev/null
+++ b/krb5-1.10.2-keytab-etype.patch
@@ -0,0 +1,332 @@
+(Had to drop the changes to src/tests/t_keytab.py, which didn't exist in 1.10.)
+
+commit d1da158f47ea604bed4d5db5e98a976a9e54ccd0
+Author: Greg Hudson <ghudson at mit.edu>
+Date: Thu Apr 19 17:55:10 2012 +0000
+
+ Unify krb5_get_init_creds_keytab code paths
+
+ Use krb5_init_creds_set_keytab in krb5_get_init_creds_keytab, so that
+ processing added to the former will be used by the latter. This is
+ slightly awkward because of the way we do the use_master fallback, in
+ that we have to duplicate some of krb5int_get_init_creds.
+
+ Based on a patch from Stef Walter.
+
+ git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25817 dc483132-0cff-0310-8789-dd5450dbe970
+
+diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps
+index fe2d54c..8c4db77 100644
+--- a/src/lib/krb5/krb/deps
++++ b/src/lib/krb5/krb/deps
+@@ -473,7 +473,8 @@ gic_keytab.so gic_keytab.po $(OUTPRE)gic_keytab.$(OBJEXT): \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
+- $(top_srcdir)/include/socket-utils.h gic_keytab.c init_creds_ctx.h
++ $(top_srcdir)/include/socket-utils.h gic_keytab.c init_creds_ctx.h \
++ int-proto.h
+ gic_opt.so gic_opt.po $(OUTPRE)gic_opt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index aaabc4e..681b648 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -542,10 +542,9 @@ krb5_init_creds_free(krb5_context context,
+ free(ctx);
+ }
+
+-static krb5_error_code
+-init_creds_get(krb5_context context,
+- krb5_init_creds_context ctx,
+- int *use_master)
++krb5_error_code
++k5_init_creds_get(krb5_context context, krb5_init_creds_context ctx,
++ int *use_master)
+ {
+ krb5_error_code code;
+ krb5_data request;
+@@ -599,7 +598,7 @@ krb5_init_creds_get(krb5_context context,
+ {
+ int use_master = 0;
+
+- return init_creds_get(context, ctx, &use_master);
++ return k5_init_creds_get(context, ctx, &use_master);
+ }
+
+ krb5_error_code KRB5_CALLCONV
+@@ -1664,7 +1663,7 @@ krb5int_get_init_creds(krb5_context context,
+ goto cleanup;
+ }
+
+- code = init_creds_get(context, ctx, use_master);
++ code = k5_init_creds_get(context, ctx, use_master);
+ if (code != 0)
+ goto cleanup;
+
+diff --git a/src/lib/krb5/krb/gic_keytab.c b/src/lib/krb5/krb/gic_keytab.c
+index 88de6a8..e59177f 100644
+--- a/src/lib/krb5/krb/gic_keytab.c
++++ b/src/lib/krb5/krb/gic_keytab.c
+@@ -26,6 +26,7 @@
+ #ifndef LEAN_CLIENT
+
+ #include "k5-int.h"
++#include "int-proto.h"
+ #include "init_creds_ctx.h"
+
+ static krb5_error_code
+@@ -87,6 +88,44 @@ krb5_init_creds_set_keytab(krb5_context context,
+ return 0;
+ }
+
++static krb5_error_code
++get_init_creds_keytab(krb5_context context, krb5_creds *creds,
++ krb5_principal client, krb5_keytab keytab,
++ krb5_deltat start_time, char *in_tkt_service,
++ krb5_get_init_creds_opt *options, int *use_master)
++{
++ krb5_error_code ret;
++ krb5_init_creds_context ctx = NULL;
++
++ ret = krb5_init_creds_init(context, client, NULL, NULL, start_time,
++ options, &ctx);
++ if (ret != 0)
++ goto cleanup;
++
++ if (in_tkt_service) {
++ ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
++ if (ret != 0)
++ goto cleanup;
++ }
++
++ ret = krb5_init_creds_set_keytab(context, ctx, keytab);
++ if (ret != 0)
++ goto cleanup;
++
++ ret = k5_init_creds_get(context, ctx, use_master);
++ if (ret != 0)
++ goto cleanup;
++
++ ret = krb5_init_creds_get_creds(context, ctx, creds);
++ if (ret != 0)
++ goto cleanup;
++
++cleanup:
++ krb5_init_creds_free(context, ctx);
++
++ return ret;
++}
++
+ krb5_error_code KRB5_CALLCONV
+ krb5_get_init_creds_keytab(krb5_context context,
+ krb5_creds *creds,
+@@ -111,10 +150,8 @@ krb5_get_init_creds_keytab(krb5_context context,
+
+ /* first try: get the requested tkt from any kdc */
+
+- ret = krb5int_get_init_creds(context, creds, client, NULL, NULL,
+- start_time, in_tkt_service, options,
+- get_as_key_keytab, (void *) keytab,
+- &use_master,NULL);
++ ret = get_init_creds_keytab(context, creds, client, keytab, start_time,
++ in_tkt_service, options, &use_master);
+
+ /* check for success */
+
+@@ -132,10 +169,9 @@ krb5_get_init_creds_keytab(krb5_context context,
+ if (!use_master) {
+ use_master = 1;
+
+- ret2 = krb5int_get_init_creds(context, creds, client, NULL, NULL,
+- start_time, in_tkt_service, options,
+- get_as_key_keytab, (void *) keytab,
+- &use_master, NULL);
++ ret2 = get_init_creds_keytab(context, creds, client, keytab,
++ start_time, in_tkt_service, options,
++ &use_master);
+
+ if (ret2 == 0) {
+ ret = 0;
+diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
+index 6b16095..899579f 100644
+--- a/src/lib/krb5/krb/int-proto.h
++++ b/src/lib/krb5/krb/int-proto.h
+@@ -196,4 +196,8 @@ krb5int_mk_setpw_req(krb5_context context, krb5_auth_context auth_context,
+ void
+ k5_ccselect_free_context(krb5_context context);
+
++krb5_error_code
++k5_init_creds_get(krb5_context context, krb5_init_creds_context ctx,
++ int *use_master);
++
+ #endif /* KRB5_INT_FUNC_PROTO__ */
+
+commit 8230c4b7b7323cdef2a6c877deb710a15380f40f
+Author: Greg Hudson <ghudson at mit.edu>
+Date: Thu Apr 19 17:55:14 2012 +0000
+
+ Use etypes from keytab in krb5_gic_keytab
+
+ When getting initial credentials with a keytab, filter the list of
+ request enctypes based on the keys in the keytab.
+
+ Based on a patch from Stef Walter.
+
+ ticket: 2131
+
+ git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25818 dc483132-0cff-0310-8789-dd5450dbe970
+
+diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
+index 3749cf9..36eb23b 100644
+--- a/src/include/k5-trace.h
++++ b/src/include/k5-trace.h
+@@ -187,6 +187,10 @@
+ #define TRACE_INIT_CREDS_GAK(c, salt, s2kparams) \
+ TRACE(c, (c, "Getting AS key, salt \"{data}\", params \"{data}\"", \
+ salt, s2kparams))
++#define TRACE_INIT_CREDS_KEYTAB_LOOKUP(c, etypes) \
++ TRACE(c, (c, "Looked up etypes in keytab: {etypes}", etypes))
++#define TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(c, code) \
++ TRACE(c, (c, "Couldn't lookup etypes in keytab: {kerr}", code))
+ #define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code) \
+ TRACE(c, (c, "Decrypt with preauth AS key failed: {kerr}", code))
+ #define TRACE_INIT_CREDS_RESTART_FAST(c) \
+diff --git a/src/lib/krb5/krb/gic_keytab.c b/src/lib/krb5/krb/gic_keytab.c
+index e59177f..3554b25 100644
+--- a/src/lib/krb5/krb/gic_keytab.c
++++ b/src/lib/krb5/krb/gic_keytab.c
+@@ -77,14 +77,132 @@ get_as_key_keytab(krb5_context context,
+ return(ret);
+ }
+
++/* Return the list of etypes available for client in keytab. */
++static krb5_error_code
++lookup_etypes_for_keytab(krb5_context context, krb5_keytab keytab,
++ krb5_principal client, krb5_enctype **etypes_out)
++{
++ krb5_kt_cursor cursor;
++ krb5_keytab_entry entry;
++ krb5_enctype *p, *etypes = NULL;
++ krb5_kvno max_kvno = 0;
++ krb5_error_code ret;
++ size_t count = 0;
++
++ *etypes_out = NULL;
++
++ if (keytab->ops->start_seq_get == NULL)
++ return EINVAL;
++ ret = krb5_kt_start_seq_get(context, keytab, &cursor);
++ 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;
++
++ if (!krb5_c_valid_enctype(entry.key.enctype))
++ continue;
++ if (!krb5_principal_compare(context, entry.principal, client))
++ continue;
++ /* Make sure our list is for the highest kvno found for client. */
++ if (entry.vno > max_kvno) {
++ free(etypes);
++ etypes = NULL;
++ count = 0;
++ max_kvno = entry.vno;
++ } else if (entry.vno != max_kvno)
++ continue;
++
++ /* Leave room for the terminator and possibly a second entry. */
++ p = realloc(etypes, (count + 3) * sizeof(*etypes));
++ if (p == NULL) {
++ ret = ENOMEM;
++ goto cleanup;
++ }
++ etypes = p;
++ etypes[count++] = entry.key.enctype;
++ /* 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)
++ etypes[count++] = ENCTYPE_DES_CBC_CRC;
++ etypes[count] = 0;
++ }
++
++ ret = 0;
++ *etypes_out = etypes;
++ etypes = NULL;
++cleanup:
++ krb5_kt_end_seq_get(context, keytab, &cursor);
++ free(etypes);
++ return ret;
++}
++
++/* Return true if search_for is in etype_list. */
++static krb5_boolean
++check_etypes_have(krb5_enctype *etype_list, krb5_enctype search_for)
++{
++ int i;
++
++ if (!etype_list)
++ return FALSE;
++
++ for (i = 0; etype_list[i] != 0; i++) {
++ if (etype_list[i] == search_for)
++ return TRUE;
++ }
++
++ return FALSE;
++}
++
+ krb5_error_code KRB5_CALLCONV
+ krb5_init_creds_set_keytab(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_keytab keytab)
+ {
++ krb5_enctype *etype_list;
++ krb5_error_code ret;
++ int i, j;
++ char *name;
++
+ ctx->gak_fct = get_as_key_keytab;
+ ctx->gak_data = keytab;
+
++ ret = lookup_etypes_for_keytab(context, keytab, ctx->request->client,
++ &etype_list);
++ if (ret) {
++ TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(context, ret);
++ return 0;
++ }
++
++ TRACE_INIT_CREDS_KEYTAB_LOOKUP(context, etype_list);
++
++ /* Filter the ktypes list based on what's in the keytab */
++ for (i = 0, j = 0; i < ctx->request->nktypes; i++) {
++ if (check_etypes_have(etype_list, ctx->request->ktype[i])) {
++ ctx->request->ktype[j] = ctx->request->ktype[i];
++ j++;
++ }
++ }
++ ctx->request->nktypes = j;
++ free(etype_list);
++
++ /* Error out now if there's no overlap. */
++ if (ctx->request->nktypes == 0) {
++ ret = krb5_unparse_name(context, ctx->request->client, &name);
++ if (ret == 0) {
++ krb5_set_error_message(context, KRB5_KT_NOTFOUND,
++ _("Keytab contains no suitable keys for "
++ "%s"), name);
++ }
++ krb5_free_unparsed_name(context, name);
++ return KRB5_KT_NOTFOUND;
++ }
++
+ return 0;
+ }
+
diff --git a/krb5.spec b/krb5.spec
index 6ad0f39..406ffa8 100644
--- a/krb5.spec
+++ b/krb5.spec
@@ -62,6 +62,7 @@ Patch101: krb5-trunk-7047.patch
Patch102: krb5-trunk-7048.patch
Patch103: krb5-1.10-gcc47.patch
Patch105: krb5-kvno-230379.patch
+Patch106: krb5-1.10.2-keytab-etype.patch
License: MIT
URL: http://web.mit.edu/kerberos/www/
@@ -234,6 +235,7 @@ ln -s NOTICE LICENSE
%patch102 -p1 -b .7048
%patch103 -p0 -b .gcc47
%patch105 -p1 -b .kvno
+%patch106 -p1 -b .keytab-etype
rm src/lib/krb5/krb/deltat.c
gzip doc/*.ps
@@ -746,6 +748,10 @@ exit 0
in the current range, in addition to the current user
- also package the PDF format admin, user, and install guides
- drop some PDFs that no longer get built right
+- add a backport of Stef's patch to set the client's list of supported
+ enctypes to match the types of keys that we have when we are using a
+ keytab to try to get initial credentials, so that a KDC won't send us
+ an AS reply that we can't encrypt (RT#2131, #748528)
* Mon May 7 2012 Nalin Dahyabhai <nalin at redhat.com>
- skip the setfscreatecon() if fopen() is passed "rb" as the open mode (part
More information about the scm-commits
mailing list