drop backports of patch for keytab-based kinit

- drop backported patches to make keytab-based authentication attempts
  work better when the client tells the KDC that it supports a particular
  cipher, but doesn't have a key for it in the keytab
This commit is contained in:
Nalin Dahyabhai 2012-11-15 15:21:19 -05:00
parent b47c708afc
commit e5f60e0625
4 changed files with 3 additions and 579 deletions

View File

@ -1,332 +0,0 @@
(Had to drop the changes to src/tests/t_keytab.py, which didn't exist in 1.10.)
commit d1da158f47ea604bed4d5db5e98a976a9e54ccd0
Author: Greg Hudson <ghudson@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@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;
}

View File

@ -1,63 +0,0 @@
Had to remove the t_keytab.py bits because that file doesn't exist in this
version. Also dropped the bit that made dbentry_supports_enctype() a static
function, since we don't have to go revert it later.
commit 18b02f3e839c007fff54fc9b693f479b7563ec73
Author: Greg Hudson <ghudson@mit.edu>
Date: Sun Jul 1 14:19:56 2012 -0400
Try harder to make keytab-based AS requests work
When making a keytab-based AS request, a client has to choose between
sending its reply key enctype preference list (the enctypes it has in
the keytab) and its session key enctype preference list (all of the
enctypes it supports). Heimdal and MIT krb5 1.11 clients send the
reply key preference list. If this list doesn't overlap with the
server principal keys (say, because the krbtgt principal has only a
DES key), then the AS request will fail.
Try to make this work by making the KDC optimistically pick the first
permitted enctype in the request as the session key, even though it
can't be certain that other KDCs in the realm support that enctype.
Make sure to exercise this case in t_keytab.py by doing a multipass
keytab kinit test.
ticket: 7190 (new)
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 3c2169e..48947c6 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1571,6 +1571,7 @@ select_session_keytype(krb5_context context, krb5_db_entry *server,
int nktypes, krb5_enctype *ktype)
{
int i;
+ krb5_enctype first_permitted = 0;
for (i = 0; i < nktypes; i++) {
if (!krb5_c_valid_enctype(ktype[i]))
@@ -1579,9 +1580,23 @@ select_session_keytype(krb5_context context, krb5_db_entry *server,
if (!krb5_is_permitted_enctype(context, ktype[i]))
continue;
+ if (first_permitted == 0)
+ first_permitted = ktype[i];
+
if (dbentry_supports_enctype(context, server, ktype[i]))
return ktype[i];
}
+
+ /*
+ * If we didn't find a match and the server is the local TGS server, this
+ * could be a keytab-based AS request where the keytab enctypes don't
+ * overlap the TGT principal enctypes. Try to make this work by using the
+ * first permitted enctype in the request, even though we can't be certain
+ * that other KDCs in the realm support it.
+ */
+ if (krb5_principal_compare(context, server->princ, tgs_server))
+ return first_permitted;
+
return 0;
}

View File

@ -1,178 +0,0 @@
Add a static definition of k5_etypes_contains(), which was introduced properly
in a different upstream commit.
commit 61659df1036d1ad6d6891293f5949e720a2028f7
Author: Greg Hudson <ghudson@mit.edu>
Date: Mon Jul 2 12:46:59 2012 -0400
Include all default etypes in gic_keytab requests
Revert 18b02f3e839c007fff54fc9b693f479b7563ec73 in the KDC. Instead,
when making an initial request with a keytab, transmit the whole
default_tkt_enctypes list, but sorted with the enctypes we have in the
keytab first. That way the KDC should prefer enctypes which we have
keys for (for both reply key and session key), but the other enctypes
are still available for use as ticket session keys.
ticket: 7190
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 48947c6..fb49973 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1571,7 +1571,6 @@ select_session_keytype(krb5_context context, krb5_db_entry *server,
int nktypes, krb5_enctype *ktype)
{
int i;
- krb5_enctype first_permitted = 0;
for (i = 0; i < nktypes; i++) {
if (!krb5_c_valid_enctype(ktype[i]))
@@ -1580,23 +1579,10 @@ select_session_keytype(krb5_context context, krb5_db_entry *server,
if (!krb5_is_permitted_enctype(context, ktype[i]))
continue;
- if (first_permitted == 0)
- first_permitted = ktype[i];
-
if (dbentry_supports_enctype(context, server, ktype[i]))
return ktype[i];
}
- /*
- * If we didn't find a match and the server is the local TGS server, this
- * could be a keytab-based AS request where the keytab enctypes don't
- * overlap the TGT principal enctypes. Try to make this work by using the
- * first permitted enctype in the request, even though we can't be certain
- * that other KDCs in the realm support it.
- */
- if (krb5_principal_compare(context, server->princ, tgs_server))
- return first_permitted;
-
return 0;
}
diff --git a/src/lib/krb5/krb/gic_keytab.c b/src/lib/krb5/krb/gic_keytab.c
index bae83db..49e5023 100644
--- a/src/lib/krb5/krb/gic_keytab.c
+++ b/src/lib/krb5/krb/gic_keytab.c
@@ -142,21 +142,42 @@ cleanup:
return ret;
}
+static krb5_boolean
+k5_etypes_contains(const krb5_enctype *list, krb5_enctype etype)
+{
+ size_t i;
+
+ for (i = 0; list[i] && list[i] != etype; i++);
+ return (list[i] == etype);
+}
-/* Return true if search_for is in etype_list. */
-static krb5_boolean
-check_etypes_have(krb5_enctype *etype_list, krb5_enctype search_for)
+/* Move the entries in keytab_list (zero-terminated) to the front of req_list
+ * (of length req_len), preserving order otherwise. */
+static krb5_error_code
+sort_enctypes(krb5_enctype *req_list, int req_len, krb5_enctype *keytab_list)
{
- int i;
-
- if (!etype_list)
- return FALSE;
-
- for (i = 0; etype_list[i] != 0; i++) {
- if (etype_list[i] == search_for)
- return TRUE;
+ krb5_enctype *save_list;
+ int save_pos, req_pos, i;
+
+ save_list = malloc(req_len * sizeof(*save_list));
+ if (save_list == NULL)
+ return ENOMEM;
+
+ /* Sort req_list entries into the front of req_list or into save_list. */
+ req_pos = save_pos = 0;
+ for (i = 0; i < req_len; i++) {
+ if (k5_etypes_contains(keytab_list, req_list[i]))
+ req_list[req_pos++] = req_list[i];
+ else
+ save_list[save_pos++] = req_list[i];
}
- return FALSE;
+ /* Put the entries we saved back in at the end, in order. */
+ for (i = 0; i < save_pos; i++)
+ req_list[req_pos++] = save_list[i];
+ assert(req_pos == req_len);
+
+ free(save_list);
+ return 0;
}
krb5_error_code KRB5_CALLCONV
@@ -166,7 +179,6 @@ krb5_init_creds_set_keytab(krb5_context context,
{
krb5_enctype *etype_list;
krb5_error_code ret;
- int i, j;
char *name;
ctx->gak_fct = get_as_key_keytab;
@@ -178,21 +190,10 @@ krb5_init_creds_set_keytab(krb5_context context,
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) {
+ /* Error out if we have no keys for the client principal. */
+ if (etype_list == NULL) {
ret = krb5_unparse_name(context, ctx->request->client, &name);
if (ret == 0) {
krb5_set_error_message(context, KRB5_KT_NOTFOUND,
@@ -203,6 +204,9 @@ krb5_init_creds_set_keytab(krb5_context context,
return KRB5_KT_NOTFOUND;
}
+ /* Sort the request enctypes so the ones in the keytab appear first. */
+ sort_enctypes(ctx->request->ktype, ctx->request->nktypes, etype_list);
+ free(etype_list);
return 0;
}
commit 7266becb5590fdf5b10463fe22bfd67650e24975
Author: Greg Hudson <ghudson@mit.edu>
Date: Mon Jul 2 12:49:22 2012 -0400
Check sort_enctypes return value in gic_keytab
diff --git a/src/lib/krb5/krb/gic_keytab.c b/src/lib/krb5/krb/gic_keytab.c
index 49e5023..38051db 100644
--- a/src/lib/krb5/krb/gic_keytab.c
+++ b/src/lib/krb5/krb/gic_keytab.c
@@ -205,9 +205,10 @@ krb5_init_creds_set_keytab(krb5_context context,
}
/* Sort the request enctypes so the ones in the keytab appear first. */
- sort_enctypes(ctx->request->ktype, ctx->request->nktypes, etype_list);
+ ret = sort_enctypes(ctx->request->ktype, ctx->request->nktypes,
+ etype_list);
free(etype_list);
- return 0;
+ return ret;
}
static krb5_error_code

View File

@ -71,10 +71,7 @@ Patch71: krb5-1.9-dirsrv-accountlock.patch
Patch75: krb5-pkinit-debug.patch
Patch86: krb5-1.9-debuginfo.patch
Patch105: krb5-kvno-230379.patch
Patch106: krb5-1.10.2-keytab-etype.patch
Patch109: krb5-1.10.3-as_rep_skew.patch
Patch110: krb5-1.10.3-keytab-etype-corners-prep.patch
Patch111: krb5-1.10.3-keytab-etype-corners.patch
Patch112: krb5-1.10.3-timeout_over.patch
License: MIT
@ -263,10 +260,7 @@ ln -s NOTICE LICENSE
#%patch75 -p1 -b .pkinit-debug
%patch86 -p0 -b .debuginfo
%patch105 -p1 -b .kvno
%patch106 -p1 -b .keytab-etype
%patch109 -p1 -b .as_rep_skew
%patch110 -p1 -b .keytab-etype-corners-prep
%patch111 -p1 -b .keytab-etype-corners
%patch112 -p1 -b .timeout_over
# Take the execute bit off of documentation.
@ -832,6 +826,9 @@ exit 0
certificate directly to verify signed-data messages that are signed with
the KDC's certificate, when the blobs don't include a copy of the KDC's
certificate
- drop backported patches to make keytab-based authentication attempts
work better when the client tells the KDC that it supports a particular
cipher, but doesn't have a key for it in the keytab
* Wed Oct 17 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.3-7
- tag a couple of other patches which we still need to be applied during