summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2012-07-02 12:46:59 -0400
committerGreg Hudson <ghudson@mit.edu>2012-07-02 12:46:59 -0400
commit61659df1036d1ad6d6891293f5949e720a2028f7 (patch)
tree5d70193bd65e72251477003fa0a22a81ae45b6e5 /src
parent8651f3339ccc5a623172a8edfb9cf522883acacd (diff)
downloadkrb5-61659df1036d1ad6d6891293f5949e720a2028f7.tar.gz
krb5-61659df1036d1ad6d6891293f5949e720a2028f7.tar.xz
krb5-61659df1036d1ad6d6891293f5949e720a2028f7.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/kdc/kdc_util.c14
-rw-r--r--src/lib/krb5/krb/gic_keytab.c56
2 files changed, 30 insertions, 40 deletions
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 48947c648..fb4997327 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 bae83dbb3..49e50235c 100644
--- a/src/lib/krb5/krb/gic_keytab.c
+++ b/src/lib/krb5/krb/gic_keytab.c
@@ -142,21 +142,34 @@ cleanup:
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)
+/* 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;
}