From b72aef2c1cbcc76f7fba14ddc54a4e66e7a4e66c Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Wed, 28 Sep 2011 17:03:15 +0000 Subject: [PATCH] Eliminate domain-based client realm walk For a very long time, KDCs have known how to perform a domain-based realm walk when serving requests for TGTs. (So if a KDC for A.B.C receives a request for krbtgt/X.B.C and doesn't have that principal, it can return one for krbtgt/B.C instead.) Performing the same heuristic on the client is unnecessary and inefficient in common cases. Add a new function k5_client_realm_path to walk_rtree.c which uses capaths values only, and returns a list of realms (as desired by get_creds.c) instead of TGT names. ticket: 6966 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25241 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/k5-int.h | 4 ++++ src/lib/krb5/krb/get_creds.c | 32 +++++-------------------- src/lib/krb5/krb/walk_rtree.c | 44 +++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 0bb4c164d..1682a345b 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -2628,6 +2628,10 @@ krb5_error_code krb5_walk_realm_tree(krb5_context, const krb5_data *, const krb5_data *, krb5_principal **, int); +krb5_error_code +k5_client_realm_path(krb5_context context, const krb5_data *client, + const krb5_data *server, krb5_data **rpath_out); + krb5_error_code krb5_auth_con_set_safe_cksumtype(krb5_context, krb5_auth_context, krb5_cksumtype); diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c index 7c8230b32..f229ba1c3 100644 --- a/src/lib/krb5/krb/get_creds.c +++ b/src/lib/krb5/krb/get_creds.c @@ -697,7 +697,7 @@ begin_get_tgt_offpath(krb5_context context, krb5_tkt_creds_context ctx) /* * To obtain a foreign TGT, we first construct a path of realms R1..Rn between - * the local realm and the target realm, using krb5_walk_realm_tree(). Usually + * the local realm and the target realm, using k5_client_realm_path(). Usually * this path is based on the domain hierarchy, but it may be altered by * configuration. * @@ -775,32 +775,16 @@ static krb5_error_code init_realm_path(krb5_context context, krb5_tkt_creds_context ctx) { krb5_error_code code; - krb5_principal *tgt_princ_list = NULL; krb5_data *realm_path; - size_t nrealms, i; + size_t nrealms; - /* Construct a list of TGT principals from client to server. We will throw - * this away after grabbing the remote realms from each principal. */ - code = krb5_walk_realm_tree(context, &ctx->client->realm, - &ctx->server->realm, - &tgt_princ_list, KRB5_REALM_BRANCH_CHAR); + /* Get the client realm path and count its length. */ + code = k5_client_realm_path(context, &ctx->client->realm, + &ctx->server->realm, &realm_path); if (code != 0) return code; - - /* Count the number of principals and allocate the realm path. */ - for (nrealms = 0; tgt_princ_list[nrealms]; nrealms++); + for (nrealms = 0; realm_path[nrealms].data != NULL; nrealms++); assert(nrealms > 1); - realm_path = k5alloc((nrealms + 1) * sizeof(*realm_path), &code); - if (realm_path == NULL) - goto cleanup; - - /* Steal the remote realm field from each TGT principal. */ - for (i = 0; i < nrealms; i++) { - assert(tgt_princ_list[i]->length == 2); - realm_path[i] = tgt_princ_list[i]->data[1]; - tgt_princ_list[i]->data[1].data = NULL; - } - realm_path[nrealms] = empty_data(); /* Initialize the realm path fields in ctx. */ krb5int_free_data_list(context, ctx->realm_path); @@ -808,10 +792,6 @@ init_realm_path(krb5_context context, krb5_tkt_creds_context ctx) ctx->last_realm = realm_path + nrealms - 1; ctx->cur_realm = realm_path; ctx->next_realm = ctx->last_realm; - realm_path = NULL; - -cleanup: - krb5_free_realm_tree(context, tgt_princ_list); return 0; } diff --git a/src/lib/krb5/krb/walk_rtree.c b/src/lib/krb5/krb/walk_rtree.c index 6aba24f8a..10711f1d6 100644 --- a/src/lib/krb5/krb/walk_rtree.c +++ b/src/lib/krb5/krb/walk_rtree.c @@ -122,6 +122,50 @@ krb5_walk_realm_tree( krb5_context context, return retval; } +krb5_error_code +k5_client_realm_path(krb5_context context, const krb5_data *client, + const krb5_data *server, krb5_data **rpath_out) +{ + krb5_error_code retval; + char **capvals; + size_t i; + krb5_data *rpath = NULL, d; + + retval = rtree_capath_vals(context, client, server, &capvals); + if (retval) + return retval; + + /* Count capaths (if any) and allocate space. Leave room for the client + * realm, server realm, and terminator. */ + for (i = 0; capvals != NULL && capvals[i] != NULL; i++); + rpath = calloc(i + 3, sizeof(*rpath)); + if (rpath == NULL) + return ENOMEM; + + /* Populate rpath with the client realm, capaths, and server realm. */ + retval = krb5int_copy_data_contents(context, client, &rpath[0]); + if (retval) + goto cleanup; + for (i = 0; capvals != NULL && capvals[i] != NULL; i++) { + d = make_data(capvals[i], strcspn(capvals[i], "\t ")); + retval = krb5int_copy_data_contents(context, &d, &rpath[i + 1]); + if (retval) + goto cleanup; + } + retval = krb5int_copy_data_contents(context, server, &rpath[i + 1]); + if (retval) + goto cleanup; + + /* Terminate rpath and return it. */ + rpath[i + 2] = empty_data(); + *rpath_out = rpath; + rpath = NULL; + +cleanup: + krb5int_free_data_list(context, rpath); + return retval; +} + /* ANL - Modified to allow Configurable Authentication Paths. * This modification removes the restriction on the choice of realm * names, i.e. they nolonger have to be hierarchical. This -- 2.26.2