Implement hierarchical referrals
This commit is contained in:

committed by
Nicolas Williams

parent
1501740952
commit
4b4036c9a6
@@ -1092,23 +1092,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
static const char *
|
||||
find_rpath(krb5_context context, Realm crealm, Realm srealm)
|
||||
{
|
||||
const char *new_realm = krb5_config_get_string(context,
|
||||
NULL,
|
||||
"capaths",
|
||||
crealm,
|
||||
srealm,
|
||||
NULL);
|
||||
return new_realm;
|
||||
}
|
||||
|
||||
|
||||
static krb5_boolean
|
||||
need_referral(krb5_context context, krb5_kdc_configuration *config,
|
||||
const KDCOptions * const options, krb5_principal server,
|
||||
@@ -1538,6 +1521,12 @@ tgs_build_reply(krb5_context context,
|
||||
krb5_keyblock sessionkey;
|
||||
krb5_kvno kvno;
|
||||
krb5_data rspac;
|
||||
const char *tgt_realm = /* Realm of TGT issuer */
|
||||
krb5_principal_get_realm(context, krbtgt->entry.principal);
|
||||
const char *our_realm = /* Realm of this KDC */
|
||||
krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1);
|
||||
char **capath = NULL;
|
||||
size_t num_capath = 0;
|
||||
|
||||
hdb_entry_ex *krbtgt_out = NULL;
|
||||
|
||||
@@ -1545,7 +1534,6 @@ tgs_build_reply(krb5_context context,
|
||||
|
||||
PrincipalName *s;
|
||||
Realm r;
|
||||
int nloop = 0;
|
||||
EncTicketPart adtkt;
|
||||
char opt_str[128];
|
||||
int signedpath = 0;
|
||||
@@ -1654,11 +1642,10 @@ server_lookup:
|
||||
kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
|
||||
goto out;
|
||||
} else if (ret == HDB_ERR_WRONG_REALM) {
|
||||
if (ref_realm)
|
||||
free(ref_realm);
|
||||
ref_realm = strdup(server->entry.principal->realm);
|
||||
if (ref_realm == NULL) {
|
||||
ret = ENOMEM;
|
||||
ret = krb5_enomem(context);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1668,12 +1655,12 @@ server_lookup:
|
||||
ref_realm, spn);
|
||||
krb5_free_principal(context, sp);
|
||||
sp = NULL;
|
||||
free(spn);
|
||||
spn = NULL;
|
||||
ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
|
||||
ref_realm, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
free(spn);
|
||||
spn = NULL;
|
||||
ret = krb5_unparse_name(context, sp, &spn);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -1685,26 +1672,36 @@ server_lookup:
|
||||
krb5_realm *realms;
|
||||
|
||||
if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
|
||||
if (nloop++ < 2) {
|
||||
new_rlm = find_rpath(context, tgt->crealm, req_rlm);
|
||||
if (capath == NULL) {
|
||||
ret = _krb5_find_capath(context, tgt->crealm, our_realm,
|
||||
req_rlm, TRUE, &capath, &num_capath);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
new_rlm = num_capath > 0 ? capath[--num_capath] : NULL;
|
||||
if (new_rlm) {
|
||||
kdc_log(context, config, 5, "krbtgt for realm %s "
|
||||
"not found, trying %s",
|
||||
req_rlm, new_rlm);
|
||||
kdc_log(context, config, 5, "krbtgt from %s via %s for "
|
||||
"realm %s not found, trying %s", tgt->crealm,
|
||||
our_realm, req_rlm, new_rlm);
|
||||
|
||||
free(ref_realm);
|
||||
ref_realm = strdup(new_rlm);
|
||||
if (ref_realm == NULL) {
|
||||
ret = krb5_enomem(context);
|
||||
goto out;
|
||||
}
|
||||
|
||||
krb5_free_principal(context, sp);
|
||||
free(spn);
|
||||
sp = NULL;
|
||||
krb5_make_principal(context, &sp, r,
|
||||
KRB5_TGS_NAME, new_rlm, NULL);
|
||||
KRB5_TGS_NAME, ref_realm, NULL);
|
||||
free(spn);
|
||||
spn = NULL;
|
||||
ret = krb5_unparse_name(context, sp, &spn);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (ref_realm)
|
||||
free(ref_realm);
|
||||
ref_realm = strdup(new_rlm);
|
||||
goto server_lookup;
|
||||
}
|
||||
}
|
||||
} else if (need_referral(context, config, &b->kdc_options, sp, &realms)) {
|
||||
if (strcmp(realms[0], sp->realm) != 0) {
|
||||
kdc_log(context, config, 5,
|
||||
@@ -1712,16 +1709,17 @@ server_lookup:
|
||||
"server %s that was not found",
|
||||
realms[0], spn);
|
||||
krb5_free_principal(context, sp);
|
||||
free(spn);
|
||||
sp = NULL;
|
||||
krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
|
||||
realms[0], NULL);
|
||||
free(spn);
|
||||
spn = NULL;
|
||||
ret = krb5_unparse_name(context, sp, &spn);
|
||||
if (ret) {
|
||||
krb5_free_host_realm(context, realms);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ref_realm)
|
||||
free(ref_realm);
|
||||
ref_realm = strdup(realms[0]);
|
||||
|
||||
@@ -1827,15 +1825,11 @@ server_lookup:
|
||||
* have been an incoming trust)
|
||||
*/
|
||||
|
||||
{
|
||||
const char *remote_realm =
|
||||
krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1);
|
||||
|
||||
ret = krb5_make_principal(context,
|
||||
&krbtgt_out_principal,
|
||||
remote_realm,
|
||||
our_realm,
|
||||
KRB5_TGS_NAME,
|
||||
remote_realm,
|
||||
our_realm,
|
||||
NULL);
|
||||
if (ret) {
|
||||
kdc_log(context, config, 0,
|
||||
@@ -1850,7 +1844,6 @@ server_lookup:
|
||||
"authz-data signatures");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = _kdc_db_fetch(context, config, krbtgt_out_principal,
|
||||
HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
|
||||
@@ -2349,6 +2342,7 @@ out:
|
||||
free(cpn);
|
||||
free(dpn);
|
||||
free(krbtgt_out_n);
|
||||
_krb5_free_capath(context, capath);
|
||||
|
||||
krb5_data_free(&rspac);
|
||||
krb5_free_keyblock_contents(context, &sessionkey);
|
||||
@@ -2367,7 +2361,6 @@ out:
|
||||
krb5_free_principal(context, dp);
|
||||
krb5_free_principal(context, sp);
|
||||
krb5_free_principal(context, krbtgt_out_principal);
|
||||
if (ref_realm)
|
||||
free(ref_realm);
|
||||
free_METHOD_DATA(&enc_pa_data);
|
||||
|
||||
|
@@ -54,6 +54,17 @@ R5=SOME-REALM5.FR
|
||||
R6=SOME-REALM6.US
|
||||
R7=SOME-REALM7.UK
|
||||
|
||||
H1=H1.$R
|
||||
H2=H2.$R
|
||||
H3=H3.$H2
|
||||
H4=H4.$H2
|
||||
|
||||
r=`echo "$R" | tr '[A-Z]' '[a-z]'`
|
||||
h1=`echo "${H1}" | tr '[A-Z]' '[a-z]'`
|
||||
h2=`echo "${H2}" | tr '[A-Z]' '[a-z]'`
|
||||
h3=`echo "${H3}" | tr '[A-Z]' '[a-z]'`
|
||||
h4=`echo "${H4}" | tr '[A-Z]' '[a-z]'`
|
||||
|
||||
port=@port@
|
||||
pwport=@pwport@
|
||||
|
||||
@@ -137,6 +148,30 @@ ${kadmin} \
|
||||
--realm-max-renewable-life=1month \
|
||||
${R7} || exit 1
|
||||
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
--realm-max-renewable-life=1month \
|
||||
${H1} || exit 1
|
||||
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
--realm-max-renewable-life=1month \
|
||||
${H2} || exit 1
|
||||
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
--realm-max-renewable-life=1month \
|
||||
${H3} || exit 1
|
||||
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
--realm-max-renewable-life=1month \
|
||||
${H4} || exit 1
|
||||
|
||||
${kadmin} \
|
||||
init \
|
||||
--realm-max-ticket-life=1day \
|
||||
@@ -149,12 +184,21 @@ ${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
|
||||
${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
|
||||
|
||||
${kadmin} add -p foo --use-defaults foo@${R} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo/host.${r}@${R} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${R2} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${R3} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${R4} || exit 1
|
||||
${kadmin5} add -p foo --use-defaults foo@${R5} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${R6} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${R7} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${H1} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo/host.${h1}@${H1} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${H2} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo/host.${h2}@${H2} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${H3} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo/host.${h3}@${H3} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo@${H4} || exit 1
|
||||
${kadmin} add -p foo --use-defaults foo/host.${h4}@${H4} || exit 1
|
||||
${kadmin} add -p bar --use-defaults bar@${R} || exit 1
|
||||
${kadmin} add -p foo --use-defaults remove@${R} || exit 1
|
||||
${kadmin} add -p nop --use-defaults ${server}@${R} || exit 1
|
||||
@@ -205,6 +249,18 @@ ${kadmin} add -p cross2 --use-defaults krbtgt/${R5}@${R6} || exit 1
|
||||
${kadmin} add -p cross1 --use-defaults krbtgt/${R7}@${R6} || exit 1
|
||||
${kadmin} add -p cross2 --use-defaults krbtgt/${R6}@${R7} || exit 1
|
||||
|
||||
${kadmin} add -p cross1 --use-defaults krbtgt/${H1}@${R} || exit 1
|
||||
${kadmin} add -p cross2 --use-defaults krbtgt/${R}@${H1} || exit 1
|
||||
|
||||
${kadmin} add -p cross1 --use-defaults krbtgt/${H2}@${R} || exit 1
|
||||
${kadmin} add -p cross2 --use-defaults krbtgt/${R}@${H2} || exit 1
|
||||
|
||||
${kadmin} add -p cross1 --use-defaults krbtgt/${H3}@${H2} || exit 1
|
||||
${kadmin} add -p cross2 --use-defaults krbtgt/${H2}@${H3} || exit 1
|
||||
|
||||
${kadmin} add -p cross1 --use-defaults krbtgt/${H3}@${H4} || exit 1
|
||||
${kadmin} add -p cross2 --use-defaults krbtgt/${H4}@${H3} || exit 1
|
||||
|
||||
${kadmin} add -p foo --use-defaults pw-expire@${R} || exit 1
|
||||
${kadmin} modify --pw-expiration-time=+1day pw-expire@${R} || exit 1
|
||||
|
||||
@@ -228,6 +284,10 @@ ${kadmin} check ${R4} || exit 1
|
||||
${kadmin5} check ${R5} || exit 1
|
||||
${kadmin} check ${R6} || exit 1
|
||||
${kadmin} check ${R7} || exit 1
|
||||
${kadmin} check ${H1} || exit 1
|
||||
${kadmin} check ${H2} || exit 1
|
||||
${kadmin} check ${H3} || exit 1
|
||||
${kadmin} check ${H4} || exit 1
|
||||
|
||||
echo "Extracting enctypes"
|
||||
${ktutil} -k ${keytab} list > tempfile || exit 1
|
||||
@@ -354,6 +414,30 @@ echo "Getting x-realm tickets with capaths for $R -> $R5"
|
||||
${kgetcred} foo@${R5} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Testing hierarchical referral logic"
|
||||
${kinit} --password-file=${objdir}/foopassword \
|
||||
-e ${aesenctype} -e ${aesenctype} \
|
||||
foo@${H3} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "Getting x-realm tickets with hierarchical referrals for $H3 -> $H1"
|
||||
${kgetcred} --hostbased --canonicalize foo host.${h1} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo "Getting x-realm tickets with hierarchical referrals for $H3 -> $R"
|
||||
${kgetcred} --hostbased --canonicalize foo host.${r} || { ec=1 ; eval "${testfailed}"; }
|
||||
echo "Getting x-realm tickets with hierarchical referrals for $H3 -> $H2"
|
||||
${kgetcred} --hostbased --canonicalize foo host.${h2} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Testing multi-hop [capaths] referral logic"
|
||||
${kinit} --password-file=${objdir}/foopassword \
|
||||
-e ${aesenctype} -e ${aesenctype} \
|
||||
foo@${H4} || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "Getting x-realm tickets with [capaths] referrals for $H4 -> $H1"
|
||||
${kgetcred} --hostbased --canonicalize foo/host.${h1}@${H4} || { ec=1 ; eval "${testfailed}"; }
|
||||
${kdestroy}
|
||||
|
||||
echo "Testing forwardable/renewable flag copying in TGS-REQ"
|
||||
${kinit} -f --renewable -r 5d --password-file=${objdir}/foopassword foo@$R || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
@@ -43,10 +43,26 @@
|
||||
TEST-HTTP.H5L.SE = {
|
||||
kdc = http/localhost:@port@
|
||||
}
|
||||
H1.TEST.H5L.SE = {
|
||||
kdc = localhost:@port@
|
||||
}
|
||||
H2.TEST.H5L.SE = {
|
||||
kdc = localhost:@port@
|
||||
}
|
||||
H3.H2.TEST.H5L.SE = {
|
||||
kdc = localhost:@port@
|
||||
}
|
||||
H4.H2.TEST.H5L.SE = {
|
||||
kdc = localhost:@port@
|
||||
}
|
||||
|
||||
[domain_realm]
|
||||
.test.h5l.se = TEST.H5L.SE
|
||||
.sub.test.h5l.se = SUB.TEST.H5L.SE
|
||||
.h1.test.h5l.se = H1.TEST.H5L.SE
|
||||
.h2.test.h5l.se = H2.TEST.H5L.SE
|
||||
.h3.h2.test.h5l.se = H3.H2.TEST.H5L.SE
|
||||
.h4.h2.test.h5l.se = H4.H2.TEST.H5L.SE
|
||||
.example.com = TEST2.H5L.SE
|
||||
localhost = TEST.H5L.SE
|
||||
.localdomain = TEST.H5L.SE
|
||||
@@ -131,3 +147,13 @@
|
||||
SOME-REALM7.UK = SOME-REALM6.US
|
||||
SOME-REALM7.UK = SOME-REALM5.FR
|
||||
}
|
||||
H4.H2.TEST.H5L.SE = {
|
||||
H1.TEST.H5L.SE = H3.H2.TEST.H5L.SE
|
||||
H1.TEST.H5L.SE = H2.TEST.H5L.SE
|
||||
H1.TEST.H5L.SE = TEST.H5L.SE
|
||||
|
||||
TEST.H5L.SE = H3.H2.TEST.H5L.SE
|
||||
TEST.H5L.SE = H2.TEST.H5L.SE
|
||||
|
||||
H2.TEST.H5L.SE = H3.H2.TEST.H5L.SE
|
||||
}
|
||||
|
Reference in New Issue
Block a user