summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2011-09-28 17:03:15 +0000
committerGreg Hudson <ghudson@mit.edu>2011-09-28 17:03:15 +0000
commitb72aef2c1cbcc76f7fba14ddc54a4e66e7a4e66c (patch)
tree37a80969b8a7c84a14d189f4bd803c97235a9c6c /src
parente3a33e5bb36c02c6646f80e3a8dd17532f4e3756 (diff)
downloadkrb5-b72aef2c1cbcc76f7fba14ddc54a4e66e7a4e66c.tar.gz
krb5-b72aef2c1cbcc76f7fba14ddc54a4e66e7a4e66c.tar.xz
krb5-b72aef2c1cbcc76f7fba14ddc54a4e66e7a4e66c.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/include/k5-int.h4
-rw-r--r--src/lib/krb5/krb/get_creds.c32
-rw-r--r--src/lib/krb5/krb/walk_rtree.c44
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
@@ -2629,6 +2629,10 @@ krb5_error_code krb5_walk_realm_tree(krb5_context, const krb5_data *,
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