Further polish and docs for hierarchical capaths

This commit is contained in:
Viktor Dukhovni
2016-08-10 22:32:52 +00:00
parent 76c596ceb8
commit 09c4e516bf
4 changed files with 42 additions and 28 deletions

View File

@@ -1673,6 +1673,7 @@ server_lookup:
if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
if (capath == NULL) { if (capath == NULL) {
/* With referalls, hierarchical capaths are always enabled */
ret = _krb5_find_capath(context, tgt->crealm, our_realm, ret = _krb5_find_capath(context, tgt->crealm, our_realm,
req_rlm, TRUE, &capath, &num_capath); req_rlm, TRUE, &capath, &num_capath);
if (ret) if (ret)

View File

@@ -395,6 +395,14 @@ specifying order can be useful where tools read and write the
configuration file without preserving parameter order. configuration file without preserving parameter order.
.Pp .Pp
Malformed rules are ignored. Malformed rules are ignored.
.It Li allow_hierarchical_capaths = Va boolean
When validating cross-realm transit paths, absent any explicit capath from the
client realm to the server realm, allow a hierarchical transit path via the
common ancestor domain of the two realms.
Defaults to true.
Note, absent an explicit setting, hierarchical capaths are always used by
the KDC when generating a referral to a destination with which is no direct
trust.
.El .El
.It Li [domain_realm] .It Li [domain_realm]
This is a list of mappings from DNS domain to Kerberos realm. This is a list of mappings from DNS domain to Kerberos realm.

View File

@@ -411,14 +411,17 @@ _krb5_free_capath(krb5_context context, char **capath)
struct hier_iter { struct hier_iter {
const char *local_realm; const char *local_realm;
const char *server_realm; const char *server_realm;
const char *lr; const char *lr; /* Pointer into tail of local realm */
const char *sr; const char *sr; /* Pointer into tail of server realm */
size_t llen; size_t llen; /* Length of local_realm */
size_t slen; size_t slen; /* Length of server_realm */
size_t len; size_t len; /* Length of common suffix */
size_t num; size_t num; /* Path element count */
}; };
/*
* Step up from local_realm to common suffix, or else down to server_realm.
*/
static const char * static const char *
hier_next(struct hier_iter *state) hier_next(struct hier_iter *state)
{ {
@@ -498,7 +501,7 @@ hier_init(struct hier_iter *state, const char *local_realm, const char *server_r
} }
/* /*
* Find a referral path from crealm to srealm via our_realm. * Find a referral path from client_realm to server_realm via local_realm.
* Either via [capaths] or hierarchicaly. * Either via [capaths] or hierarchicaly.
*/ */
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
@@ -506,12 +509,10 @@ _krb5_find_capath(krb5_context context,
const char *client_realm, const char *client_realm,
const char *local_realm, const char *local_realm,
const char *server_realm, const char *server_realm,
krb5_boolean use_hierachical, krb5_boolean use_hierarchical,
char ***rpath, char ***rpath,
size_t *npath) size_t *npath)
{ {
krb5_boolean maybe = (TRUE == 1) ? 2 : 1; /* Neither TRUE nor FALSE */
krb5_boolean b;
char **confpath; char **confpath;
char **capath; char **capath;
struct hier_iter hier_state; struct hier_iter hier_state;
@@ -529,9 +530,9 @@ _krb5_find_capath(krb5_context context,
/* /*
* With a [capaths] setting from the client to the server we look for our * With a [capaths] setting from the client to the server we look for our
* own realm in the list. If our own realm is not present, we return the * own realm in the list. If our own realm is not present, we return the
* first element. Otherwise, we return the next element, or possibly NULL. * full list. Otherwise, we return our realm's successors, or possibly
* Ignoring a [capaths] settings risks loops plus would violate explicit * NULL. Ignoring a [capaths] settings risks loops plus would violate
* policy and the principle of least surpise. * explicit policy and the principle of least surpise.
*/ */
if (confpath != NULL) { if (confpath != NULL) {
char **start = confpath; char **start = confpath;
@@ -543,12 +544,16 @@ _krb5_find_capath(krb5_context context,
start = rp+1; start = rp+1;
n = rp - start; n = rp - start;
if (n == 0) if (n == 0) {
krb5_config_free_strings(confpath);
return 0; return 0;
}
capath = calloc(n + 1, sizeof(*capath)); capath = calloc(n + 1, sizeof(*capath));
if (capath == NULL) if (capath == NULL) {
krb5_config_free_strings(confpath);
return krb5_enomem(context); return krb5_enomem(context);
}
for (i = 0, rp = start; *rp; rp++) { for (i = 0, rp = start; *rp; rp++) {
if ((capath[i++] = strdup(*rp)) == NULL) { if ((capath[i++] = strdup(*rp)) == NULL) {
@@ -564,18 +569,17 @@ _krb5_find_capath(krb5_context context,
return 0; return 0;
} }
/* /* The use_hierarchical flag makes hierarchical path lookup unconditional */
* With hierarchical referrals, we ignore the client realm, and build a if (! use_hierarchical &&
* path forward from our own realm! ! krb5_config_get_bool_default(context, NULL, TRUE, "libdefaults",
*/ "allow_hierarchical_capaths", NULL))
b = krb5_config_get_bool_default(context, NULL, maybe, "realms",
local_realm, "hier_capaths", NULL);
if (b == maybe)
b = krb5_config_get_bool_default(context, NULL, TRUE, "libdefaults",
"hier_capaths", NULL);
if (b == FALSE)
return 0; return 0;
/*
* When validating transit paths, local_realm == client_realm. Otherwise,
* with hierarchical referrals, they may differ, and we may be building a
* path forward from our own realm!
*/
hier_init(&hier_state, local_realm, server_realm); hier_init(&hier_state, local_realm, server_realm);
if (hier_state.num == 0) if (hier_state.num == 0)
return 0; return 0;
@@ -610,8 +614,9 @@ krb5_check_transited(krb5_context context,
size_t i = 0; size_t i = 0;
size_t j = 0; size_t j = 0;
/* In transit checks hierarchical capaths are optional */
ret = _krb5_find_capath(context, client_realm, client_realm, server_realm, ret = _krb5_find_capath(context, client_realm, client_realm, server_realm,
TRUE, &capath, &num_capath); FALSE, &capath, &num_capath);
if (ret) if (ret)
return ret; return ret;

View File

@@ -410,7 +410,7 @@ struct entry libdefaults_entries[] = {
{ "fcc-mit-ticketflags", krb5_config_string, check_boolean, 0 }, { "fcc-mit-ticketflags", krb5_config_string, check_boolean, 0 },
{ "forward", krb5_config_string, check_boolean, 0 }, { "forward", krb5_config_string, check_boolean, 0 },
{ "forwardable", krb5_config_string, check_boolean, 0 }, { "forwardable", krb5_config_string, check_boolean, 0 },
{ "hier_capaths", krb5_config_string, check_boolean, 0 }, { "allow_hierarchical_capaths", krb5_config_string, check_boolean, 0 },
{ "host_timeout", krb5_config_string, check_time, 0 }, { "host_timeout", krb5_config_string, check_time, 0 },
{ "http_proxy", krb5_config_string, check_host /* XXX */, 0 }, { "http_proxy", krb5_config_string, check_host /* XXX */, 0 },
{ "ignore_addresses", krb5_config_string, NULL, 0 }, { "ignore_addresses", krb5_config_string, NULL, 0 },
@@ -481,7 +481,7 @@ struct entry realms_entries[] = {
{ "auth_to_local_names", krb5_config_string, NULL, 0 }, { "auth_to_local_names", krb5_config_string, NULL, 0 },
{ "default_domain", krb5_config_string, NULL, 0 }, { "default_domain", krb5_config_string, NULL, 0 },
{ "forwardable", krb5_config_string, check_boolean, 0 }, { "forwardable", krb5_config_string, check_boolean, 0 },
{ "hier_capaths", krb5_config_string, check_boolean, 0 }, { "allow_hierarchical_capaths", krb5_config_string, check_boolean, 0 },
{ "kdc", krb5_config_string, check_host, 0 }, { "kdc", krb5_config_string, check_host, 0 },
{ "kpasswd_server", krb5_config_string, check_host, 0 }, { "kpasswd_server", krb5_config_string, check_host, 0 },
{ "krb524_server", krb5_config_string, check_host, 0 }, { "krb524_server", krb5_config_string, check_host, 0 },