/*
* This program is intended to be run from a python script as:
*
- * gcred nametype princname
+ * gcred [-f] [-t] nametype princname
*
* where nametype is one of "unknown", "principal", "srv-inst", and "srv-hst",
* and princname is the name of the service principal. gcred acquires
* the server principal name of the obtained credentials to stdout and exits
* with status 0. On failure, gcred displays the error message for the failed
* operation to stderr and exits with status 1.
+ *
+ * The -f and -t flags set the KRB5_GC_FORWARDABLE and KRB5_GC_NO_TRANSIT_CHECK
+ * options respectively.
*/
#include "k5-int.h"
check(krb5_init_context(&ctx));
- while ((c = getopt(argc, argv, "f")) != -1) {
+ while ((c = getopt(argc, argv, "ft")) != -1) {
switch (c) {
case 'f':
options |= KRB5_GC_FORWARDABLE;
break;
+ case 't':
+ options |= KRB5_GC_NO_TRANSIT_CHECK;
+ break;
default:
abort();
}
{'realm': 'B', 'krb5_conf': capaths},
{'realm': 'C', 'krb5_conf': capaths},
{'realm': 'D', 'krb5_conf': capaths}))
-test_kvno(r1, r4.host_princ, 'KDC capaths')
-check_klist(r1, (tgt(r1, r1), tgt(r4, r3), r4.host_princ))
+r1client = r1.special_env('client', False, krb5_conf={'capaths': None})
+test_kvno(r1, r4.host_princ, 'KDC capaths', r1client)
+check_klist(r1, (tgt(r1, r1), r4.host_princ))
stop(r1, r2, r3, r4)
# A capaths value of '.' should enforce direct cross-realm, with no
check_klist(r1, (tgt(r1, r1), tgt(r3, r2)))
stop(r1, r2, r3)
-# Test a different kind of transited error. The KDC for D does not
-# recognize B as an intermediate realm for A->C, so it refuses to
-# verify the krbtgt/C@B ticket in the TGS AP-REQ.
+# Test server transited checking. The KDC for C recognizes B as an
+# intermediate realm for A->C, but the server environment does not.
+# The server should honor the ticket if the transited-policy-checked
+# flag is set, but not if it isn't. (It is only possible for our KDC
+# to issue a ticket without the transited-policy-checked flag with
+# reject_bad_transit=false.)
+mark('server transited checking')
+capaths = {'capaths': {'A': {'C': 'B'}}}
+noreject = {'realms': {'$realm': {'reject_bad_transit': 'false'}}}
+r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)),
+ args=({'realm': 'A', 'krb5_conf': capaths},
+ {'realm': 'B'},
+ {'realm': 'C', 'krb5_conf': capaths,
+ 'kdc_conf': noreject}))
+r3server = r3.special_env('server', False, krb5_conf={'capaths': None})
+# Process a ticket with the transited-policy-checked flag set.
+shutil.copy(r1.ccache, r1.ccache + '.copy')
+r1.run(['./gcred', 'principal', r3.host_princ])
+os.rename(r1.ccache, r3.ccache)
+r3.run(['./rdreq', r3.host_princ], env=r3server, expected_msg='0 success')
+# Try again with the transited-policy-checked flag unset.
+os.rename(r1.ccache + '.copy', r1.ccache)
+r1.run(['./gcred', '-t', 'principal', r3.host_princ])
+os.rename(r1.ccache, r3.ccache)
+r3.run(['./rdreq', r3.host_princ], env=r3server,
+ expected_msg='43 Illegal cross-realm ticket')
+stop(r1, r2, r3)
+
+# Test a four-realm scenario. This test used to result in an "Illegal
+# cross-realm ticket" error as the KDC for D would refuse to process
+# the cross-realm ticket from C. Now that we honor the
+# transited-policy-checked flag in krb5_rd_req(), it instead issues a
+# policy error as in the three-realm scenario.
mark('transited error (four realms)')
capaths = {'capaths': {'A': {'D': ['B', 'C'], 'C': 'B'}, 'B': {'D': 'C'}}}
r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)),
{'realm': 'C', 'krb5_conf': capaths},
{'realm': 'D'}))
r1.run([kvno, r4.host_princ], expected_code=1,
- expected_msg='Illegal cross-realm ticket')
+ expected_msg='KDC policy rejects request')
check_klist(r1, (tgt(r1, r1), tgt(r4, r3)))
stop(r1, r2, r3, r4)