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 +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 +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 - skip the setfscreatecon() if fopen() is passed "rb" as the open mode (part