summaryrefslogtreecommitdiffstats
path: root/third_party/heimdal/tests/kdc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/tests/kdc')
-rw-r--r--third_party/heimdal/tests/kdc/Makefile.am443
-rw-r--r--third_party/heimdal/tests/kdc/NTMakefile35
-rw-r--r--third_party/heimdal/tests/kdc/an2ln-db.txt144
-rw-r--r--third_party/heimdal/tests/kdc/check-authz.in134
-rw-r--r--third_party/heimdal/tests/kdc/check-bx509.in1127
-rw-r--r--third_party/heimdal/tests/kdc/check-canon.in210
-rw-r--r--third_party/heimdal/tests/kdc/check-cc.in203
-rw-r--r--third_party/heimdal/tests/kdc/check-delegation.in152
-rw-r--r--third_party/heimdal/tests/kdc/check-des.in155
-rw-r--r--third_party/heimdal/tests/kdc/check-digest.in291
-rw-r--r--third_party/heimdal/tests/kdc/check-fast.in212
-rw-r--r--third_party/heimdal/tests/kdc/check-hdb-mitdb.in111
-rw-r--r--third_party/heimdal/tests/kdc/check-httpkadmind.in842
-rw-r--r--third_party/heimdal/tests/kdc/check-iprop.in611
-rw-r--r--third_party/heimdal/tests/kdc/check-kadmin.in456
-rw-r--r--third_party/heimdal/tests/kdc/check-kdc-weak.in37
-rw-r--r--third_party/heimdal/tests/kdc/check-kdc.in1131
-rw-r--r--third_party/heimdal/tests/kdc/check-keys.in104
-rw-r--r--third_party/heimdal/tests/kdc/check-kinit.in149
-rw-r--r--third_party/heimdal/tests/kdc/check-kpasswdd.in194
-rw-r--r--third_party/heimdal/tests/kdc/check-pkinit.in393
-rw-r--r--third_party/heimdal/tests/kdc/check-referral.in301
-rw-r--r--third_party/heimdal/tests/kdc/check-tester.in121
-rw-r--r--third_party/heimdal/tests/kdc/check-uu.in131
-rw-r--r--third_party/heimdal/tests/kdc/donotexists.txt1
-rw-r--r--third_party/heimdal/tests/kdc/hdb-mitdbbin0 -> 16384 bytes
-rw-r--r--third_party/heimdal/tests/kdc/hdb-mitdb.kadm5bin0 -> 8192 bytes
-rw-r--r--third_party/heimdal/tests/kdc/hdb-mitdb.mkeybin0 -> 30 bytes
-rw-r--r--third_party/heimdal/tests/kdc/heimdal.acl10
-rw-r--r--third_party/heimdal/tests/kdc/iprop-acl1
-rw-r--r--third_party/heimdal/tests/kdc/k5login/foo1
-rw-r--r--third_party/heimdal/tests/kdc/k5login/mapped_user11
-rw-r--r--third_party/heimdal/tests/kdc/kdc-tester1.json31
-rw-r--r--third_party/heimdal/tests/kdc/kdc-tester2.json12
-rw-r--r--third_party/heimdal/tests/kdc/kdc-tester3.json23
-rw-r--r--third_party/heimdal/tests/kdc/kdc-tester4.json.in22
-rw-r--r--third_party/heimdal/tests/kdc/krb5-authz.conf.in26
-rw-r--r--third_party/heimdal/tests/kdc/krb5-authz2.conf.in27
-rw-r--r--third_party/heimdal/tests/kdc/krb5-bx509.conf.in182
-rw-r--r--third_party/heimdal/tests/kdc/krb5-canon.conf.in100
-rw-r--r--third_party/heimdal/tests/kdc/krb5-canon2.conf.in97
-rw-r--r--third_party/heimdal/tests/kdc/krb5-cccol.conf.in165
-rw-r--r--third_party/heimdal/tests/kdc/krb5-hdb-mitdb.conf.in60
-rw-r--r--third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in98
-rw-r--r--third_party/heimdal/tests/kdc/krb5-kcm.conf.in165
-rw-r--r--third_party/heimdal/tests/kdc/krb5-pkinit.conf.in82
-rw-r--r--third_party/heimdal/tests/kdc/krb5.conf.in175
-rw-r--r--third_party/heimdal/tests/kdc/krb5.conf.keys.in19
-rw-r--r--third_party/heimdal/tests/kdc/leaks-kill.sh27
-rw-r--r--third_party/heimdal/tests/kdc/ntlm-user-file.txt1
-rw-r--r--third_party/heimdal/tests/kdc/pki-mapping2
-rw-r--r--third_party/heimdal/tests/kdc/uuserver.txt4
-rw-r--r--third_party/heimdal/tests/kdc/wait-kdc.sh65
53 files changed, 9084 insertions, 0 deletions
diff --git a/third_party/heimdal/tests/kdc/Makefile.am b/third_party/heimdal/tests/kdc/Makefile.am
new file mode 100644
index 0000000..09f6953
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/Makefile.am
@@ -0,0 +1,443 @@
+include $(top_srcdir)/Makefile.am.common
+
+noinst_DATA = \
+ an2ln-db.txt \
+ kdc-tester4.json \
+ krb5.conf \
+ krb5-kcm.conf \
+ krb5-cccol.conf \
+ krb5-authz.conf \
+ krb5-authz2.conf \
+ krb5-canon.conf \
+ krb5-canon2.conf \
+ krb5-hdb-mitdb.conf \
+ krb5-weak.conf \
+ krb5-pkinit.conf \
+ krb5-bx509.conf \
+ krb5-httpkadmind.conf \
+ krb5-pkinit-win.conf \
+ krb5-master2.conf \
+ krb5-slave2.conf \
+ krb5-slave.conf
+
+check_SCRIPTS = $(SCRIPT_TESTS)
+
+SCRIPT_TESTS = \
+ check-authz \
+ check-canon \
+ check-cc \
+ check-delegation \
+ check-des \
+ check-digest \
+ check-fast \
+ check-kadmin \
+ check-hdb-mitdb \
+ check-kdc \
+ check-kdc-weak \
+ check-keys \
+ check-kpasswdd \
+ check-pkinit \
+ check-bx509 \
+ check-httpkadmind \
+ check-iprop \
+ check-referral \
+ check-tester \
+ check-uu
+
+TESTS = $(SCRIPT_TESTS)
+
+port = 49188
+admport = 49189
+admport2 = 49190
+pwport = 49191
+restport = 49192
+restport2 = 49193
+ipropport = 49194
+ipropport2 = 49195
+pkinit_ticket_max_life_from_cert = 0
+
+if HAVE_DLOPEN
+do_dlopen = -e 's,[@]DLOPEN[@],true,g'
+else
+do_dlopen = -e 's,[@]DLOPEN[@],false,g'
+endif
+
+do_subst = $(heim_verbose)sed $(do_dlopen) \
+ -e 's,[@]env_setup[@],$(top_builddir)/tests/bin/setup-env,g' \
+ -e 's,[@]top_srcdir[@],$(top_srcdir),g' \
+ -e 's,[@]srcdir[@],$(srcdir),g' \
+ -e 's,[@]port[@],$(port),g' \
+ -e 's,[@]admport[@],$(admport),g' \
+ -e 's,[@]admport2[@],$(admport2),g' \
+ -e 's,[@]bx509port[@],$(restport),g' \
+ -e 's,[@]restport[@],$(restport),g' \
+ -e 's,[@]restport2[@],$(restport2),g' \
+ -e 's,[@]pwport[@],$(pwport),g' \
+ -e 's,[@]ipropport[@],$(ipropport),g' \
+ -e 's,[@]ipropport2[@],$(ipropport2),g' \
+ -e 's,[@]objdir[@],$(top_builddir)/tests/kdc,g' \
+ -e 's,[@]top_builddir[@],$(top_builddir),g' \
+ -e 's,[@]db_type[@],$(db_type),g' \
+ -e 's,[@]max_life_from_cert[@],$(pkinit_ticket_max_life_from_cert),g' \
+ -e 's,[@]ENABLE_AFS_STRING_TO_KEY[@],$(ENABLE_AFS_STRING_TO_KEY),' \
+ -e 's,[@]ENABLE_AFS_STRING_TO_KEY[@],$(ENABLE_AFS_STRING_TO_KEY),' \
+ -e 's,[@]EGREP[@],$(EGREP),g' \
+ -e 's,[@]MITKRB5[@],$(MITKRB5),g'
+
+chmod = chmod
+
+LDADD = ../../lib/krb5/libkrb5.la $(LIB_roken)
+
+check-authz: check-authz.in Makefile krb5-authz.conf krb5-authz2.conf
+ $(do_subst) < $(srcdir)/check-authz.in > check-authz.tmp && \
+ $(chmod) +x check-authz.tmp && \
+ mv check-authz.tmp check-authz
+
+check-canon: check-canon.in Makefile krb5-canon.conf krb5-canon2.conf
+ $(do_subst) < $(srcdir)/check-canon.in > check-canon.tmp && \
+ $(chmod) +x check-canon.tmp && \
+ mv check-canon.tmp check-canon
+
+check-cc: check-cc.in Makefile
+ $(do_subst) < $(srcdir)/check-cc.in > check-cc.tmp && \
+ $(chmod) +x check-cc.tmp && \
+ mv check-cc.tmp check-cc
+
+check-delegation: check-delegation.in Makefile
+ $(do_subst) < $(srcdir)/check-delegation.in > check-delegation.tmp && \
+ $(chmod) +x check-delegation.tmp && \
+ mv check-delegation.tmp check-delegation
+
+check-des: check-des.in Makefile krb5.conf
+ $(do_subst) < $(srcdir)/check-des.in > check-des.tmp && \
+ $(chmod) +x check-des.tmp && \
+ mv check-des.tmp check-des
+
+check-hdb-mitdb: check-hdb-mitdb.in Makefile krb5-hdb-mitdb.conf
+ $(do_subst) < $(srcdir)/check-hdb-mitdb.in > check-hdb-mitdb.tmp && \
+ $(chmod) +x check-hdb-mitdb.tmp && \
+ mv check-hdb-mitdb.tmp check-hdb-mitdb
+
+check-fast: check-fast.in Makefile
+ $(do_subst) < $(srcdir)/check-fast.in > check-fast.tmp && \
+ $(chmod) +x check-fast.tmp && \
+ mv check-fast.tmp check-fast
+
+check-kdc: check-kdc.in Makefile
+ $(do_subst) < $(srcdir)/check-kdc.in > check-kdc.tmp && \
+ $(chmod) +x check-kdc.tmp && \
+ mv check-kdc.tmp check-kdc
+
+check-kdc-weak: check-kdc-weak.in Makefile
+ $(do_subst) < $(srcdir)/check-kdc-weak.in > check-kdc-weak.tmp && \
+ $(chmod) +x check-kdc-weak.tmp && \
+ mv check-kdc-weak.tmp check-kdc-weak
+
+check-tester: check-tester.in kdc-tester4.json Makefile
+ $(do_subst) < $(srcdir)/check-tester.in > check-tester.tmp && \
+ $(chmod) +x check-tester.tmp && \
+ mv check-tester.tmp check-tester
+
+check-keys: check-keys.in Makefile
+ $(do_subst) < $(srcdir)/check-keys.in > check-keys.tmp && \
+ $(chmod) +x check-keys.tmp && \
+ mv check-keys.tmp check-keys
+
+check-kinit: check-kinit.in Makefile
+ $(do_subst) < $(srcdir)/check-kinit.in > check-kinit.tmp && \
+ $(chmod) +x check-kinit.tmp && \
+ mv check-kinit.tmp check-kinit
+
+check-kadmin: check-kadmin.in Makefile
+ $(do_subst) < $(srcdir)/check-kadmin.in > check-kadmin.tmp && \
+ $(chmod) +x check-kadmin.tmp && \
+ mv check-kadmin.tmp check-kadmin
+
+check-uu: check-uu.in Makefile
+ $(do_subst) < $(srcdir)/check-uu.in > check-uu.tmp && \
+ $(chmod) +x check-uu.tmp && \
+ mv check-uu.tmp check-uu
+
+check-pkinit: check-pkinit.in Makefile krb5-pkinit.conf krb5-pkinit2.conf
+ $(do_subst) < $(srcdir)/check-pkinit.in > check-pkinit.tmp && \
+ $(chmod) +x check-pkinit.tmp && \
+ mv check-pkinit.tmp check-pkinit
+
+check-bx509: check-bx509.in Makefile krb5-bx509.conf
+ $(do_subst) < $(srcdir)/check-bx509.in > check-bx509.tmp && \
+ $(chmod) +x check-bx509.tmp && \
+ mv check-bx509.tmp check-bx509
+
+check-httpkadmind: check-httpkadmind.in Makefile krb5-httpkadmind.conf
+ $(do_subst) < $(srcdir)/check-httpkadmind.in > check-httpkadmind.tmp && \
+ $(chmod) +x check-httpkadmind.tmp && \
+ mv check-httpkadmind.tmp check-httpkadmind
+
+check-iprop: check-iprop.in Makefile krb5.conf krb5-master2.conf krb5-slave.conf krb5-slave2.conf
+ $(do_subst) < $(srcdir)/check-iprop.in > check-iprop.tmp && \
+ $(chmod) +x check-iprop.tmp && \
+ mv check-iprop.tmp check-iprop
+
+check-digest: check-digest.in Makefile
+ $(do_subst) < $(srcdir)/check-digest.in > check-digest.tmp && \
+ $(chmod) +x check-digest.tmp && \
+ mv check-digest.tmp check-digest
+
+check-referral: check-referral.in Makefile
+ $(do_subst) < $(srcdir)/check-referral.in > check-referral.tmp && \
+ $(chmod) +x check-referral.tmp && \
+ mv check-referral.tmp check-referral
+
+check-kpasswdd: check-kpasswdd.in Makefile
+ $(do_subst) < $(srcdir)/check-kpasswdd.in > check-kpasswdd.tmp && \
+ $(chmod) +x check-kpasswdd.tmp && \
+ mv check-kpasswdd.tmp check-kpasswdd
+
+kdc-tester4.json: kdc-tester4.json.in Makefile
+ $(do_subst) < $(srcdir)/kdc-tester4.json.in > kdc-tester4.json.tmp && \
+ mv kdc-tester4.json.tmp kdc-tester4.json
+
+krb5.conf: krb5.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],false,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]messages[@],messages,g' \
+ -e 's,[@]ipropstats[@],iprop-stats,g' \
+ -e 's,[@]signalsocket[@],signal,g' \
+ -e 's,[@]kdc[@],,g' < $(srcdir)/krb5.conf.in > krb5.conf.tmp && \
+ mv krb5.conf.tmp krb5.conf
+
+krb5-kcm.conf: krb5-kcm.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],false,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]kdc[@],,g' < $(srcdir)/krb5-kcm.conf.in > krb5-kcm.conf.tmp && \
+ mv krb5-kcm.conf.tmp krb5-kcm.conf
+
+krb5-cccol.conf: krb5-cccol.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],false,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]kdc[@],,g' < $(srcdir)/krb5-cccol.conf.in > krb5-cccol.conf.tmp && \
+ mv krb5-cccol.conf.tmp krb5-cccol.conf
+
+krb5-authz.conf: krb5-authz.conf.in Makefile
+ $(do_subst) < $(srcdir)/krb5-authz.conf.in > krb5-authz.conf.tmp && \
+ mv krb5-authz.conf.tmp krb5-authz.conf
+
+krb5-authz2.conf: krb5-authz2.conf.in Makefile
+ $(do_subst) < $(srcdir)/krb5-authz2.conf.in > krb5-authz2.conf.tmp && \
+ mv krb5-authz2.conf.tmp krb5-authz2.conf
+
+krb5-canon.conf: krb5-canon.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],false,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]kdc[@],,g' < $(srcdir)/krb5-canon.conf.in > krb5-canon.conf.tmp && \
+ mv krb5-canon.conf.tmp krb5-canon.conf
+
+krb5-canon2.conf: krb5-canon2.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],false,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]kdc[@],,g' < $(srcdir)/krb5-canon2.conf.in > krb5-canon2.conf.tmp && \
+ mv krb5-canon2.conf.tmp krb5-canon2.conf
+
+krb5-hdb-mitdb.conf: krb5-hdb-mitdb.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],false,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]kdc[@],,g' < $(srcdir)/krb5-hdb-mitdb.conf.in > krb5-hdb-mitdb.conf.tmp && \
+ mv krb5-hdb-mitdb.conf.tmp krb5-hdb-mitdb.conf
+
+krb5-weak.conf: krb5.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],true,g' \
+ -e 's,[@]dk[@],default_keys = aes256-cts-hmac-sha1-96:pw-salt arcfour-hmac-md5:pw-salt des3-cbc-sha1:pw-salt des:pw-salt,g' \
+ -e 's,[@]messages[@],messages,g' \
+ -e 's,[@]signalsocket[@],signal,g' \
+ -e 's,[@]ipropstats[@],iprop-stats,g' \
+ -e 's,[@]kdc[@],,g' < $(srcdir)/krb5.conf.in > krb5-weak.conf.tmp && \
+ mv krb5-weak.conf.tmp krb5-weak.conf
+
+krb5-slave.conf: krb5.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],true,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]messages[@],messages,g' \
+ -e 's,[@]signalsocket[@],signal2,g' \
+ -e 's,[@]ipropstats[@],iprop-stats,g' \
+ -e 's,[@]kdc[@],.slave,g' < $(srcdir)/krb5.conf.in > krb5-slave.conf.tmp && \
+ mv krb5-slave.conf.tmp krb5-slave.conf
+
+krb5-master2.conf: krb5.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],true,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]messages[@],messages2,g' \
+ -e 's,[@]signalsocket[@],signal2,g' \
+ -e 's,[@]ipropstats[@],iprop-stats2,g' \
+ -e 's,[@]kdc[@],.slave,g' < $(srcdir)/krb5.conf.in > krb5-master2.conf.tmp && \
+ mv krb5-master2.conf.tmp krb5-master2.conf
+
+krb5-slave2.conf: krb5.conf.in Makefile
+ $(do_subst) \
+ -e 's,[@]WEAK[@],true,g' \
+ -e 's,[@]dk[@],,g' \
+ -e 's,[@]messages[@],messages2,g' \
+ -e 's,[@]signalsocket[@],signal3,g' \
+ -e 's,[@]ipropstats[@],iprop-stats2,g' \
+ -e 's,[@]kdc[@],.slave2,g' < $(srcdir)/krb5.conf.in > krb5-slave2.conf.tmp && \
+ mv krb5-slave2.conf.tmp krb5-slave2.conf
+
+krb5-pkinit.conf: krb5-pkinit.conf.in Makefile
+ $(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-pkinit.conf.in > krb5-pkinit.conf.tmp && \
+ mv krb5-pkinit.conf.tmp krb5-pkinit.conf
+
+krb5-pkinit2.conf : pkinit_ticket_max_life_from_cert = 30d
+
+krb5-pkinit2.conf: krb5-pkinit.conf.in Makefile
+ $(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-pkinit.conf.in > krb5-pkinit2.conf.tmp && \
+ mv krb5-pkinit2.conf.tmp krb5-pkinit2.conf
+
+krb5-bx509.conf: krb5-bx509.conf.in Makefile
+ $(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-bx509.conf.in > krb5-bx509.conf.tmp && \
+ mv krb5-bx509.conf.tmp krb5-bx509.conf
+
+krb5-httpkadmind.conf: krb5-httpkadmind.conf.in Makefile
+ $(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-httpkadmind.conf.in > krb5-httpkadmind.conf.tmp && \
+ mv krb5-httpkadmind.conf.tmp krb5-httpkadmind.conf
+
+krb5-pkinit-win.conf: krb5-pkinit.conf.in Makefile
+ $(do_subst) -e 's,[@]w2k[@],yes,g' < $(srcdir)/krb5-pkinit.conf.in > krb5-pkinit-win.conf.tmp && \
+ mv krb5-pkinit-win.conf.tmp krb5-pkinit-win.conf
+
+clean: clean-am
+ rm -rf cc_dir authz_dir
+
+CLEANFILES= \
+ $(TESTS) \
+ *.crt \
+ *.der \
+ *.log \
+ *.pem \
+ *.pid \
+ *.tmp \
+ acache.krb5 \
+ barpassword \
+ ca.crt \
+ cache.krb5 \
+ cache2.krb5 \
+ cdigest-reply \
+ client-cache \
+ curlheaders \
+ current-db* \
+ current.log* \
+ digest-reply \
+ extracted_config \
+ extracted_keytab* \
+ foopassword \
+ foopassword.rkpty \
+ iprop-stats \
+ iprop-stats2 \
+ iprop.keytab \
+ ipropd.dumpfile \
+ kdc-tester4.json \
+ krb5-authz.conf \
+ krb5-authz2.conf \
+ krb5-canon.conf \
+ krb5-canon2.conf \
+ krb5-cc.conf \
+ krb5-cccol.conf \
+ krb5-hdb-mitdb.conf \
+ krb5-master2.conf \
+ krb5-pkinit-win.conf \
+ krb5-pkinit.conf \
+ krb5-pkinit2.conf \
+ krb5-bx509.conf \
+ krb5-httpkadmind.conf \
+ krb5-slave2.conf \
+ krb5-slave.conf \
+ krb5-weak.conf \
+ krb5.conf \
+ krb5.conf.keys \
+ kt \
+ leaks-log \
+ localname \
+ malloc-log \
+ malloc-log-master \
+ malloc-log-slave \
+ messages.log2 \
+ negotiate-token \
+ notfoopassword \
+ o2cache.krb5 \
+ o2digest-reply \
+ ocache.krb5 \
+ out-log \
+ req \
+ response-headers \
+ s2digest-reply \
+ sdb \
+ sdigest-init \
+ sdigest-reply \
+ server.keytab \
+ signal \
+ signal2 \
+ signal3 \
+ tempfile \
+ test-rc-file.rc \
+ ukt \
+ uuserver.log
+
+EXTRA_DIST = \
+ NTMakefile \
+ an2ln-db.txt \
+ check-authz.in \
+ check-bx509.in \
+ check-canon.in \
+ check-cc.in \
+ check-delegation.in \
+ check-des.in \
+ check-digest.in \
+ check-fast.in \
+ check-hdb-mitdb.in \
+ check-httpkadmind.in \
+ check-iprop.in \
+ check-kadmin.in \
+ check-kdc-weak.in \
+ check-kdc.in \
+ check-keys.in \
+ check-kinit.in \
+ check-kpasswdd.in \
+ check-pkinit.in \
+ check-referral.in \
+ check-tester.in \
+ check-uu.in \
+ donotexists.txt \
+ hdb-mitdb \
+ hdb-mitdb.kadm5 \
+ hdb-mitdb.mkey \
+ heimdal.acl \
+ iprop-acl \
+ k5login/foo \
+ k5login/mapped_user1 \
+ kdc-tester1.json \
+ kdc-tester2.json \
+ kdc-tester3.json \
+ kdc-tester4.json.in \
+ krb5-authz.conf.in \
+ krb5-authz2.conf.in \
+ krb5-bx509.conf.in \
+ krb5-canon.conf.in \
+ krb5-canon2.conf.in \
+ krb5-cccol.conf.in \
+ krb5-hdb-mitdb.conf.in \
+ krb5-httpkadmind.conf.in \
+ krb5-pkinit.conf.in \
+ krb5.conf.in \
+ krb5.conf.keys.in \
+ leaks-kill.sh \
+ ntlm-user-file.txt \
+ pki-mapping \
+ uuserver.txt \
+ wait-kdc.sh
diff --git a/third_party/heimdal/tests/kdc/NTMakefile b/third_party/heimdal/tests/kdc/NTMakefile
new file mode 100644
index 0000000..16ca0a7
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/NTMakefile
@@ -0,0 +1,35 @@
+########################################################################
+#
+# Copyright (c) 2009, Secure Endpoints Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+RELDIR=tests\kdc
+
+!include ../../windows/NTMakefile.w32
+
diff --git a/third_party/heimdal/tests/kdc/an2ln-db.txt b/third_party/heimdal/tests/kdc/an2ln-db.txt
new file mode 100644
index 0000000..0b2fe38
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/an2ln-db.txt
@@ -0,0 +1,144 @@
+0575ee035f72dfb1 junk
+074897aaa3c4eace junk
+0c0015d1cb0edf2e junk
+15c02bb64902a207 junk
+1730cb4567c1bfce junk
+17c6e78171587710 junk
+21bef891f06af28e junk
+2358b67cdd649987 junk
+2b334ee5d32eb55b junk
+2f4cd4424e58822d junk
+4758f671c662b7e2 junk
+4bf0af25dd5211bd junk
+4d7f715b271ddb10 junk
+4f701fa5a4055c00 junk
+4f7634440d7bef3a junk
+5593a6bc03a68a3d junk
+5652948873ae4a9b junk
+5ababa9c833ce592 junk
+5c2fb83355b59cf1 junk
+5cf29f522abbcbe1 junk
+5d184a0f45bdaf61 junk
+70a01e2a09ba4b40 junk
+75bdfdb4c9c9b26b junk
+787aa58456e66463 junk
+788fa38b04026ca9 junk
+79ad9f69fb354592 junk
+7a686ba61c736eb1 junk
+807644c5c50f29d5 junk
+826de82aa81c3f8a junk
+85316d269114d787 junk
+86b7d20af35cffba junk
+895ca88e162d398f junk
+9008213d189aac2b junk
+98a51d5c9a172691 junk
+9af7d4a596944dcf junk
+a094067ad439189c junk
+a86904ae8f55df9e junk
+aa3ae6e252f65711 junk
+b19ffc6336a23be3 junk
+b4e37e4d23c4d7be junk
+b5c8b14d1e8ae7cb junk
+b9365f7ec3b0d52c junk
+bar/mapped1@TEST2.H5L.SE foobar
+bar/mapped2@TEST2.H5L.SE foobaz
+c118fb30610b8011 junk
+c19ffa62f50ad8f7 junk
+c9fce89738e25054 junk
+cb4555bb49891436 junk
+ccfb9930466fe627 junk
+cd2e8bc1fd014a86 junk
+d0d8dfeddf1b1eaa junk
+d22ff9ea01dfe15f junk
+d2bce251fcf6d5a3 junk
+d377b118646db95d junk
+d42fd3b12935a24a junk
+d948845a3b0068ac junk
+dbb143ecf6019b50 junk
+dbe41b5888e50c9c junk
+dd7a0a53ed569e21 junk
+dd82f76178ff0315 junk
+e1d62414205aa5a1 junk
+e3156ded04399027 junk
+e6bccd04c18fbd2e junk
+e9cb04e892e8f072 junk
+ebb5773344e4ade4 junk
+ef08d2dc9fef4f05 junk
+f59975170a04e071 junk
+f75338796ea735f0 junk
+f8cd2e85efa891af junk
+fd6e5e417b8296a7 junk
+foo/mapped1@TEST2.H5L.SE foo_mapped
+mapped1@TEST2.H5L.SE m1
+mapped1@TEST3.H5L.SE mapped1
+mapped2@TEST2.H5L.SE m2
+mapped2@TEST3.H5L.SE mapped2
+user1@@TEST.H5L.SE mapped_user1
+z008213d189aac2b junk
+z07644c5c50f29d5 junk
+z094067ad439189c junk
+z0a01e2a09ba4b40 junk
+z0d8dfeddf1b1eaa junk
+z118fb30610b8011 junk
+z19ffa62f50ad8f7 junk
+z19ffc6336a23be3 junk
+z1bef891f06af28e junk
+z1d62414205aa5a1 junk
+z22ff9ea01dfe15f junk
+z26de82aa81c3f8a junk
+z2bce251fcf6d5a3 junk
+z3156ded04399027 junk
+z358b67cdd649987 junk
+z377b118646db95d junk
+z42fd3b12935a24a junk
+z4e37e4d23c4d7be junk
+z5316d269114d787 junk
+z575ee035f72dfb1 junk
+z593a6bc03a68a3d junk
+z59975170a04e071 junk
+z5bdfdb4c9c9b26b junk
+z5c02bb64902a207 junk
+z5c8b14d1e8ae7cb junk
+z652948873ae4a9b junk
+z6b7d20af35cffba junk
+z6bccd04c18fbd2e junk
+z730cb4567c1bfce junk
+z74897aaa3c4eace junk
+z75338796ea735f0 junk
+z758f671c662b7e2 junk
+z7c6e78171587710 junk
+z86904ae8f55df9e junk
+z87aa58456e66463 junk
+z88fa38b04026ca9 junk
+z8a51d5c9a172691 junk
+z8cd2e85efa891af junk
+z9365f7ec3b0d52c junk
+z948845a3b0068ac junk
+z95ca88e162d398f junk
+z9ad9f69fb354592 junk
+z9cb04e892e8f072 junk
+z9fce89738e25054 junk
+za3ae6e252f65711 junk
+za686ba61c736eb1 junk
+zababa9c833ce592 junk
+zaf7d4a596944dcf junk
+zb334ee5d32eb55b junk
+zb4555bb49891436 junk
+zbb143ecf6019b50 junk
+zbb5773344e4ade4 junk
+zbe41b5888e50c9c junk
+zbf0af25dd5211bd junk
+zc0015d1cb0edf2e junk
+zc2fb83355b59cf1 junk
+zcf29f522abbcbe1 junk
+zcfb9930466fe627 junk
+zd184a0f45bdaf61 junk
+zd2e8bc1fd014a86 junk
+zd6e5e417b8296a7 junk
+zd7a0a53ed569e21 junk
+zd7f715b271ddb10 junk
+zd82f76178ff0315 junk
+zf08d2dc9fef4f05 junk
+zf4cd4424e58822d junk
+zf701fa5a4055c00 junk
+zf7634440d7bef3a junk
diff --git a/third_party/heimdal/tests/kdc/check-authz.in b/third_party/heimdal/tests/kdc/check-authz.in
new file mode 100644
index 0000000..02015b3
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-authz.in
@@ -0,0 +1,134 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="."
+
+. ${env_setup}
+
+srcdir="${top_srcdir}/tests/kdc"
+test_alname="${test_alname} --simple"
+
+rm -f localname
+
+check_localname() {
+ stderr=
+ if test "$2" -ne 0; then
+ stderr="2>/dev/null"
+ fi
+ eval ${test_alname} "'$1'" > localname $stderr
+ status=$?
+ if test $status -ne "$2"; then
+ echo "Unexpected exit code from test_alname $1: $status"
+ exit 1
+ fi
+ if test $status -ne 0; then
+ return 0
+ fi
+ read lname < localname
+ if test "X$lname" != "X$3"; then
+ echo "Unexpected mapping of $1: $lname"
+ exit 1
+ fi
+ return 0
+}
+
+R=TEST.H5L.SE
+R2=TEST2.H5L.SE
+R3=TEST3.H5L.SE
+R4=TEST4.H5L.SE
+
+KRB5_CONFIG="${objdir}/krb5-authz.conf"
+export KRB5_CONFIG
+
+echo "Checking 1-component principal names in default realms"
+check_localname mapped1@${R} 0 foo || exit 1
+check_localname mapped2@${R} 0 bar || exit 1
+check_localname mapped1@${R2} 0 m1 || exit 1
+check_localname mapped2@${R2} 0 m2 || exit 1
+check_localname mapped1@${R3} 0 mapped1 || exit 1
+check_localname mapped2@${R3} 0 mapped2 || exit 1
+check_localname notmapped1@${R} 0 notmapped1 || exit 1
+check_localname notmapped1@${R2} 0 notmapped1 || exit 1
+check_localname notmapped1@${R3} 0 notmapped1 || exit 1
+
+echo "Checking 1-component principal names in non-default realm"
+check_localname mapped1@${R4} 1 || exit 1
+check_localname notmapped1@${R4} 1 || exit 1
+
+echo "Checking 2-component principal names"
+check_localname foo/mapped1@${R} 0 foo || exit 1
+check_localname foo/mapped2@${R} 0 bar || exit 1
+check_localname bar/mapped1@${R2} 0 foobar || exit 1
+check_localname bar/mapped2@${R2} 0 foobaz || exit 1
+check_localname foo/mapped1@${R3} 1 || exit 1
+check_localname bar/mapped1@${R3} 1 || exit 1
+check_localname foo/notmapped1@${R} 1 || exit 1
+check_localname bar/notmapped1@${R2} 1 || exit 1
+
+echo "Checking 2-component principal names in non-default realm"
+check_localname foo/mapped1@${R4} 1 || exit 1
+check_localname bar/mapped1@${R4} 1 || exit 1
+check_localname foo/notmapped1@${R4} 1 || exit 1
+check_localname bar/notmapped1@${R4} 1 || exit 1
+
+echo "Checking for overflow"
+test_alname="${test_alname} --simple --lname-size=1"
+check_localname mapped1@${R} 3 || exit 1
+check_localname mapped2@${R} 3 || exit 1
+check_localname mapped1@${R2} 3 || exit 1
+check_localname mapped2@${R2} 3 || exit 1
+check_localname mapped1@${R3} 3 || exit 1
+check_localname mapped2@${R3} 3 || exit 1
+
+echo "Checking krb5_kuserok()"
+${test_kuserok} random-princ@RANDOM-REALM foo > /dev/null || exit 1
+${test_kuserok} mapped1@${R} foo > /dev/null || exit 1
+${test_kuserok} mapped1@${R2} m1 > /dev/null || exit 1
+${test_kuserok} notmapped1@${R3} notmapped1 > /dev/null || exit 1
+${test_kuserok} this-better-not-exist@NOR-THIS foo > /dev/null && exit 1
+
+KRB5_CONFIG="${objdir}/krb5-authz2.conf"
+export KRB5_CONFIG
+
+echo "Checking krb5_kuserok() (with authoritative k5login files)"
+${test_kuserok} random-princ@RANDOM-REALM foo > /dev/null || exit 1
+${test_kuserok} mapped1@${R} foo > /dev/null && exit 1
+${test_kuserok} mapped1@${R2} m1 > /dev/null || exit 1
+${test_kuserok} notmapped1@${R3} notmapped1 > /dev/null || exit 1
+${test_kuserok} this-better-not-exist@NOR-THIS foo > /dev/null && exit 1
+
+rm -f messages.log
+
+exit 0
diff --git a/third_party/heimdal/tests/kdc/check-bx509.in b/third_party/heimdal/tests/kdc/check-bx509.in
new file mode 100644
index 0000000..6d894ef
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-bx509.in
@@ -0,0 +1,1127 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+umask 077
+
+R=TEST.H5L.SE
+DCs="DC=test,DC=h5l,DC=se"
+
+port=@port@
+bx509port=@bx509port@
+
+server=datan.test.h5l.se
+otherserver=other.test.h5l.se
+
+kadmin="${kadmin} -l -r $R"
+bx509d="${bx509d} --allow-GET --reverse-proxied -p $bx509port -H $server --cert=${objdir}/bx509.pem -t"
+kdc="${kdc} --addresses=localhost -P $port"
+
+cachefile="${objdir}/cache.krb5"
+cache="FILE:${cachefile}"
+cachefile2="${objdir}/cache2.krb5"
+cache2="FILE:${cachefile2}"
+keyfile="${hx509_data}/key.der"
+keyfile2="${hx509_data}/key2.der"
+kt=${objdir}/kt
+keytab=FILE:${kt}
+ukt=${objdir}/ukt
+ukeytab=FILE:${ukt}
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist2="${klist} --hidden -v -c $cache2"
+klistjson="${klist} --json -c $cache"
+klist="${klist} --hidden -v -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+test_csr_authorizer="$test_csr_authorizer -A $objdir/authz_dir -S $objdir"
+kx509="${kx509} -c $cache"
+
+KRB5_CONFIG="${objdir}/krb5-bx509.conf"
+export KRB5_CONFIG
+
+HEIM_PIDFILE_DIR="${objdir}/"
+export HEIM_PIDFILE_DIR
+
+HEIM_IPC_DIR=$objdir
+export HEIM_IPC_DIR
+
+rsa=yes
+pkinit=no
+if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then
+ rsa=no
+fi
+if ${hxtool} info | grep 'rand: not available' > /dev/null ; then
+ rsa=no
+fi
+
+if ${kinit} --help 2>&1 | grep "CA certificates" > /dev/null; then
+ pkinit=yes
+fi
+
+# If we doesn't support pkinit and have RSA, give up
+if test "$pkinit" != yes -o "$rsa" != yes ; then
+ exit 77
+fi
+
+
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+rm -f *.pem *.crt *.der
+rm -rf authz_dir
+
+mkdir -p authz_dir
+
+> messages.log
+
+kdcpid=
+bx509pid=
+test_csr_authorizer_pid=
+trap 'kill -9 ${kdcpid} ${bx509pid} ${test_csr_authorizer_pid}; echo signal killing kdc, bx509d, and test_csr_authorizer; exit 1;' EXIT
+
+# csr_grant ext-type value grantee_principal
+csr_grant() {
+ mkdir -p "${objdir}/authz_dir/${3}"
+ touch "${objdir}/authz_dir/${3}/${1}=${2}"
+}
+
+csr_revoke() {
+ rm -rf "${objdir}/authz_dir"
+ mkdir -p "${objdir}/authz_dir"
+}
+
+# get_cert "" curl-opts
+# get_cert "&qparams" curl-opts
+get_cert() {
+ url="http://${server}:${bx509port}/bx509?csr=$csr${1}"
+ shift
+ curl -g --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "$@" "$url"
+}
+
+get_with_token() {
+ if [ -n "$csr" ]; then
+ url="http://${server}:${bx509port}/${1}?csr=$csr${2}"
+ else
+ url="http://${server}:${bx509port}/${1}?${2}"
+ fi
+ shift 2
+
+ curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ -D response-headers \
+ "$@" "$url" &&
+ { echo "GET w/o CSRF token succeeded!"; exit 2; }
+ curl -g --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ -D response-headers \
+ "$@" "$url"
+ grep ^X-CSRF-Token: response-headers >/dev/null ||
+ { echo "GET w/o CSRF token did not output a CSRF token!"; exit 2; }
+ curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \
+ "$@" "$url" ||
+ { echo "GET w/ CSRF failed"; exit 2; }
+}
+
+get_via_POST() {
+ endpoint=$1
+ shift
+
+ curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ -X POST -D response-headers \
+ "$@" "http://${server}:${bx509port}/${endpoint}" &&
+ { echo "POST w/o CSRF token succeeded!"; exit 2; }
+ curl -g --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ -X POST -D response-headers \
+ "$@" "http://${server}:${bx509port}/${endpoint}"
+ grep ^X-CSRF-Token: response-headers >/dev/null ||
+ { echo "POST w/o CSRF token did not output a CSRF token!"; exit 2; }
+ curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \
+ -X POST \
+ "$@" "http://${server}:${bx509port}/${endpoint}" ||
+ { echo "POST w/ CSRF failed"; exit 2; }
+}
+
+rm -f $kt $ukt
+$ktutil -k $keytab add -r -V 1 -e aes128-cts-hmac-sha1-96 \
+ -p HTTP/datan.test.h5l.se@${R} ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+$ktutil -k $keytab list ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+$kimpersonate --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \
+ -c foo@${R} -s HTTP/datan.test.h5l.se@${R} ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+$klist ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+
+echo "Setting up certificates"
+# We need:
+#
+# - a CA certificate for issuing client certificates
+# - a CA certificate for issuing server certificates
+# - a CA certificate for issuing mixed certificates
+# - a certificate for bx509 itself (well, not in reverse proxy mode, but we'll
+# make one anyways)
+
+# Make the realm's user cert issuer CA certificate.
+#
+# NOTE WELL: We need all three KeyUsage values listed below!
+# We also need this to be of type "pkinit-kdc",
+# which means we'll get an appropriate EKU OID as
+# well.
+$hxtool ca --issue-ca --self-signed --type=pkinit-kdc \
+ --ku=digitalSignature --ku=keyCertSign --ku=cRLSign \
+ --pk-init-principal=krbtgt/${R}@${R} \
+ --generate-key=rsa --key-bits=1024 \
+ --subject="OU=Users,CN=KDC,${DCs}" \
+ --certificate=PEM-FILE:"${objdir}/user-issuer.pem" ||
+ { echo "failed to setup CA certificate"; exit 2; }
+
+# We'll use the user cert issuer as the PKINIT anchor, allowing bx509-issued
+# certificates to be used for PKINIT. Though we won't be testing PKINIT here
+# -- we test kx509->PKINIT in check-pkinit.
+cp ${objdir}/user-issuer.pem ${objdir}/pkinit-anchor.pem
+
+# Put the cert alone in the trust anchors file
+ex "${objdir}/pkinit-anchor.pem" <<"EOF"
+/-----BEGIN CERTIFICATE-----
+1,.-1 d
+wq
+EOF
+
+$hxtool ca --issue-ca --self-signed \
+ --ku=digitalSignature --ku=keyCertSign --ku=cRLSign \
+ --generate-key=rsa --key-bits=1024 \
+ --subject="OU=Servers,CN=KDC,${DCs}" \
+ --certificate=PEM-FILE:"${objdir}/server-issuer.pem" ||
+ { echo "failed to setup CA certificate"; exit 2; }
+
+$hxtool ca --issue-ca --self-signed \
+ --ku=digitalSignature --ku=keyCertSign --ku=cRLSign \
+ --generate-key=rsa --key-bits=1024 \
+ --subject="OU=Users,CN=KDC,${DCs}" \
+ --certificate=PEM-FILE:"${objdir}/mixed-issuer.pem" ||
+ { echo "failed to setup CA certificate"; exit 2; }
+
+$hxtool ca --issue-ca --type=https-negotiate-server \
+ --ca-certificate=PEM-FILE:"${objdir}/server-issuer.pem" \
+ --ku=digitalSignature --pk-init-principal=HTTP/${server}@${R}\
+ --generate-key=rsa --key-bits=1024 --subject="" \
+ --certificate=PEM-FILE:"${objdir}/bx509.pem" ||
+ { echo "failed to setup CA certificate"; exit 2; }
+
+# XXX Before starting bx509d let us use kdc test programs to check that:
+#
+# - the negotiate token validator plugin works
+# - the authz_dir CSR authorizer plugin works
+# - the KDC CA tester program works
+
+echo "Check gss-token and Negotiate token validator plugin"
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server | tr A B)
+$test_token_validator -a datan.test.h5l.se Negotiate "$token" &&
+ { echo "Negotiate token validator accepted invalid token"; exit 2; }
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+$test_token_validator -a datan.test.h5l.se Negotiate "$token" ||
+ { echo "Negotiate token validator failed to validate valid token"; exit 2; }
+
+
+echo "Starting CSR authorizer IPC service"
+$test_csr_authorizer --server --daemon ||
+ { echo "Failed to start test_csr_authorizer service"; exit 2; }
+test_csr_authorizer_pid=`getpid test_csr_authorizer`
+
+# Make a CSR for foo@$R
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" --kerberos=foo@$R \
+ ${objdir}/req ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+echo "Test CSR authorizer IPC service (deny foo@$R to san_pkinit=foo@$R)"
+csr_revoke
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R &&
+ { echo "CSR authorizer IPC service granted foo@$R"; exit 2; }
+
+echo "Test CSR authorizer IPC service (grant foo@$R to san_pkinit=foo@$R)"
+csr_grant san_pkinit foo@$R foo@${R}
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R ||
+ { echo "CSR authorizer IPC service rejected foo@$R"; exit 2; }
+
+# Make a CSR for bar@$R
+$hxtool request-create --subject='' --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" --kerberos=bar@$R \
+ ${objdir}/req ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+echo "Test CSR authorizer IPC service (deny foo@$R to san_pkinit=bar@$R)"
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R &&
+ { echo "CSR authorizer IPC service accepted foo@$R"; exit 2; }
+
+echo "Test CSR authorizer IPC service (grant foo@$R to san_pkinit=bar@$R)"
+csr_grant san_pkinit foo@$R bar@${R}
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R &&
+ { echo "CSR authorizer IPC service accepted foo@$R"; exit 2; }
+
+# Make a CSR for foo@$R and bar@$R
+$hxtool request-create --subject='' --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" \
+ --kerberos=foo@$R --kerberos=bar@$R \
+ ${objdir}/req ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+# Check that the authorizer does mark foo@$R as approved even though it denies
+# the overall request because it rejects bar@$R
+echo "Test CSR authorizer IPC service (partial authz)"
+csr_revoke
+csr_grant san_pkinit foo@$R foo@${R}
+# Check that the authorizer grants foo@$R
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=foo@$R ||
+ { echo "CSR authorizer IPC service partial approval check fail"; exit 2; }
+# Check that the authorizer rejects bar@$R
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=bar@$R &&
+ { echo "CSR authorizer IPC service partial approval check fail"; exit 2; }
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=foo@$R san_pkinit=bar@$R &&
+ { echo "CSR authorizer IPC service partial approval check fail"; exit 2; }
+
+echo "Making a plain CSR"
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+rm -f trivial.pem server.pem email.pem
+
+echo "Testing plain user cert issuance KDC CA"
+$test_kdc_ca -a bx509 -A foo@${R} PKCS10:${objdir}/req \
+ PEM-FILE:${objdir}/trivial.pem ||
+ { echo "Trivial offline CA test failed"; exit 2; }
+$hxtool print --content PEM-FILE:${objdir}/trivial.pem ||
+ { echo "Trivial offline CA test failed"; exit 2; }
+$hxtool acert --end-entity \
+ --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \
+ -P "foo@${R}" "FILE:${objdir}/trivial.pem" ||
+ { echo "Trivial offline CA test failed"; exit 2; }
+$hxtool acert --expr="%{certificate.subject} == \"OU=Users,CN=KDC,$DCs\"" \
+ --lacks-private-key "FILE:${objdir}/trivial.pem" ||
+ { echo "Trivial offline CA test failed (issuer private keys included!!)"; exit 2; }
+
+echo "Testing other cert issuance KDC CA"
+csr_revoke
+# https server cert
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" \
+ --eku=id_pkix_kp_serverAuth \
+ --dnsname=foo.test.h5l.se "${objdir}/req" ||
+ { echo "Failed to make a CSR with a dNSName SAN request"; exit 2; }
+$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \
+ PEM-FILE:${objdir}/server.pem &&
+ { echo "Trivial offline CA test failed: unauthorized issuance (dNSName)"; exit 2; }
+csr_grant san_dnsname foo.test.h5l.se foo@${R}
+csr_grant eku 1.3.6.1.5.5.7.3.1 foo@${R}
+$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \
+ PEM-FILE:${objdir}/server.pem ||
+ { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; }
+$hxtool print --content PEM-FILE:${objdir}/server.pem ||
+ { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; }
+$hxtool acert --expr="%{certificate.subject} == \"OU=Servers,CN=KDC,$DCs\"" \
+ --lacks-private-key "FILE:${objdir}/server.pem" ||
+ { echo "Trivial offline CA test failed (issuer private keys included!!)"; exit 2; }
+# email cert
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" \
+ --eku=id_pkix_kp_clientAuth \
+ --email=foo@test.h5l.se "${objdir}/req" ||
+ { echo "Failed to make a CSR with an rfc822Name SAN request"; exit 2; }
+$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \
+ PEM-FILE:${objdir}/email.pem &&
+ { echo "Offline CA test failed: unauthorized issuance (dNSName)"; exit 2; }
+csr_grant san_email foo@test.h5l.se foo@${R}
+csr_grant eku 1.3.6.1.5.5.7.3.2 foo@${R}
+$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \
+ PEM-FILE:${objdir}/email.pem ||
+ { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; }
+$hxtool print --content PEM-FILE:${objdir}/email.pem ||
+ { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; }
+$hxtool acert --expr="%{certificate.subject} == \"OU=Users,CN=KDC,$DCs\"" \
+ --lacks-private-key "FILE:${objdir}/email.pem" ||
+ { echo "Offline CA test failed (issuer private keys included!!)"; exit 2; }
+
+if ! which curl; then
+ echo "curl is not available -- not testing bx509d"
+ sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1
+ trap '' EXIT
+ exit 77
+fi
+
+if ! test -x ${objdir}/../../kdc/bx509d; then
+ echo "Configured w/o libmicrohttpd -- not testing bx509d"
+ sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1
+ trap '' EXIT
+ exit 77
+fi
+
+echo "Creating database"
+rm -f $kt $ukt
+${kadmin} <<EOF || exit 1
+init --realm-max-ticket-life=1day --realm-max-renewable-life=1month ${R}
+add -r --use-defaults foo@${R}
+add -r --use-defaults bar@${R}
+add -r --use-defaults baz@${R}
+add -r --use-defaults raz@${R}
+modify --pkinit-acl="CN=foo,DC=test,DC=h5l,DC=se" foo@${R}
+add -r --use-defaults HTTP/${server}@${R}
+ext_keytab -r -k $keytab HTTP/${server}@${R}
+add -r --use-defaults HTTP/${otherserver}@${R}
+ext_keytab -r -k $ukeytab foo@${R}
+EOF
+
+echo "Starting kdc";
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+${kdestroy}
+${kinit} -kt $ukeytab foo@${R} || exit 1
+$klist || { echo "failed to kinit"; exit 2; }
+
+
+echo "Starting bx509d"
+${bx509d} --daemon || { echo "bx509 failed to start"; exit 2; }
+bx509pid=`getpid bx509d`
+
+ec=0
+
+rm -f trivial.pem server.pem email.pem
+
+echo "Making a plain CSR (with BasicConstraints requesting CA cert)"
+csr_revoke
+$hxtool request-create --subject='CN=H5LCA' --generate-key=rsa --key-bits=1024 \
+ --ca --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+# XXX Add autoconf check for curl?
+# Create a barebones bx509 HTTP/1.1 client test program?
+
+echo "Fail to get a certificate using a CSR requesting a CA cert"
+# Encode the CSR in base64, then URL-encode it
+csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then
+ echo 'Issued a certificate for a CSR that requested a CA cert!'
+ exit 1
+else
+ echo 'CSRs requesting CA certs properly rejected'
+fi
+
+echo "Making a plain CSR (with BasicConstraints requesting EE cert)"
+csr_revoke
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --ee --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+echo "Fetching a trivial user certificate"
+# Encode the CSR in base64, then URL-encode it
+csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then
+ $hxtool print --content "FILE:${objdir}/trivial.pem"
+ if $hxtool acert --end-entity \
+ --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \
+ -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate with a CSR w/ BasicConstraints requesting EE cert!'
+ else
+ echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)'
+ exit 1
+ fi
+ if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \
+ --has-private-key "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ fi
+else
+ echo 'Failed to get a certificate with a CSR w/ BasicConstraints requesting EE cert!'
+ exit 1
+fi
+
+echo "Making a plain CSR"
+csr_revoke
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+echo "Fetching a trivial user certificate (no authentication, must fail)"
+# Encode the CSR in base64, then URL-encode it
+csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
+if (set -vx;
+ curl -g --resolve ${server}:${bx509port}:127.0.0.1 \
+ -sf -o "${objdir}/trivial.pem" \
+ "http://${server}:${bx509port}/bx509?csr=$csr"); then
+ $hxtool print --content "FILE:${objdir}/trivial.pem"
+ echo 'Got a certificate without authenticating!'
+ exit 1
+fi
+
+echo "Fetching a trivial user certificate"
+# Encode the CSR in base64, then URL-encode it
+csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then
+ $hxtool print --content "FILE:${objdir}/trivial.pem"
+ if $hxtool acert --end-entity \
+ --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \
+ -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ else
+ echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)'
+ exit 1
+ fi
+ if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \
+ --has-private-key "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ fi
+else
+ echo 'Failed to get a certificate!'
+ exit 1
+fi
+
+echo "Fetching a trivial user certificate (with POST, no auth, must fail)"
+# Encode the CSR in base64; curl will URL-encode it for us
+csr=$($rkbase64 -- ${objdir}/req)
+if (set -vx;
+ curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \
+ -X POST -D response-headers \
+ -F csr="$csr" -o "${objdir}/trivial.pem" \
+ "http://${server}:${bx509port}/bx509" ); then
+ $hxtool print --content "FILE:${objdir}/trivial.pem"
+ echo 'Got a certificate without authenticating!'
+ exit 1
+fi
+
+echo "Fetching a trivial user certificate (with POST)"
+# Encode the CSR in base64; curl will URL-encode it for us
+csr=$($rkbase64 -- ${objdir}/req)
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx;
+ get_via_POST bx509 -F csr="$csr" -o "${objdir}/trivial.pem"); then
+ $hxtool print --content "FILE:${objdir}/trivial.pem"
+ if $hxtool acert --end-entity \
+ --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \
+ -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ else
+ echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)'
+ exit 1
+ fi
+ if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \
+ --has-private-key "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ fi
+else
+ echo 'Failed to get a certificate!'
+ exit 1
+fi
+
+echo "Checking that authorization is enforced"
+csr_revoke
+get_cert '&rfc822Name=foo@bar.example' -vvv -o "${objdir}/bad1.pem"
+if (set -vx; get_cert '&rfc822Name=foo@bar.example' -sf -o "${objdir}/trivial.pem"); then
+ $hxtool print --content "FILE:${objdir}/bad1.pem"
+ echo 'Obtained a client certificate for a non-granted name!'
+ exit 1
+else
+ echo 'Correctly failed to get a client certificate for a non-granted name'
+fi
+
+if (set -vx; get_cert "&dNSName=$server" -sf -o "${objdir}/bad2.pem"); then
+ $hxtool print --content "FILE:${objdir}/bad2.pem"
+ echo 'Obtained a server certificate for a non-granted name!'
+ exit 1
+else
+ echo 'Correctly failed to get a server certificate for a non-granted name'
+fi
+
+echo "Fetching a server certificate with one dNSName SAN"
+csr_grant san_dnsname $server foo@${R}
+if (set -vx; get_cert "&dNSName=$server" -sf -o "${objdir}/server.pem"); then
+ $hxtool print --content "FILE:${objdir}/server.pem"
+ if (set -vx; $hxtool acert --expr="%{certificate.subject} == \"\"" \
+ --end-entity -P foo@${R} \
+ "FILE:${objdir}/server.pem"); then
+ echo 'Got a broken server certificate (has PKINIT SAN)'
+ exit 1
+ elif $hxtool acert --end-entity -D $server "FILE:${objdir}/server.pem"; then
+ echo 'Successfully obtained a server certificate!'
+ else
+ echo 'Got a broken server certificate'
+ exit 1
+ fi
+else
+ echo 'Failed to get a server certificate!'
+ exit 1
+fi
+
+echo "Fetching a server certificate with two dNSName SANs"
+csr_grant san_dnsname "second-$server" foo@${R}
+if (set -vx;
+ get_cert "&dNSName=${server}&dNSName=second-$server" -sf \
+ -o "${objdir}/server2.pem"); then
+ $hxtool print --content "FILE:${objdir}/server2.pem"
+ if $hxtool acert --expr="%{certificate.subject} == \"\"" \
+ --end-entity -P foo@${R} \
+ "FILE:${objdir}/server2.pem"; then
+ echo 'Got a broken server certificate (has PKINIT SAN)'
+ exit 1
+ elif $hxtool acert --end-entity -D "$server" \
+ -D "second-$server" \
+ "FILE:${objdir}/server2.pem"; then
+ echo 'Successfully obtained a server certificate with two dNSName SANs!'
+ else
+ echo 'Got a broken server certificate (wanted two dNSName SANs)'
+ exit 1
+ fi
+else
+ echo 'Failed to get a server certificate with two dNSName SANs!'
+ exit 1
+fi
+
+echo "Fetching an email certificate"
+csr_grant san_email foo@bar.example foo@${R}
+if (set -vx; get_cert "&rfc822Name=foo@bar.example" -sf -o "${objdir}/email.pem"); then
+ $hxtool print --content "FILE:${objdir}/email.pem"
+ if $hxtool acert --end-entity -P "foo@${R}" "FILE:${objdir}/email.pem"; then
+ echo 'Got a broken email certificate (has PKINIT SAN)'
+ exit 1
+ elif $hxtool acert --expr="%{certificate.subject} == \"\"" \
+ --end-entity -M foo@bar.example \
+ "FILE:${objdir}/email.pem"; then
+ echo 'Successfully obtained a email certificate!'
+ else
+ echo 'Got a broken email certificate'
+ exit 1
+ fi
+else
+ echo 'Failed to get an email certificate!'
+ exit 1
+fi
+
+echo "Fetch TGT (not granted for other)"
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx;
+ curl -o "${cachefile2}" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8"); then
+ echo "Got a TGT with /get-tgt end-point when not granted!"
+ exit 2
+fi
+
+echo "Fetch TGT"
+csr_grant san_pkinit foo@${R} foo@${R}
+csr_grant eku 1.3.6.1.5.2.3.4 foo@${R}
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -o "${cachefile2}" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgt?address=8.8.8.8"); then
+ echo "Failed to get a TGT with /get-tgt end-point"
+ exit 2
+fi
+
+${klist2} | grep Addresses:.IPv4:8.8.8.8 ||
+ { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; }
+
+echo "Fetch TGT (inception)"
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -o "${cachefile}" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgt?address=8.8.8.8"); then
+ echo "Failed to get a TGT with /get-tgt end-point"
+ exit 2
+fi
+${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+${klist} | grep Addresses:.IPv4:8.8.8.8 ||
+ { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; }
+
+echo "Fetch TGT (for other)"
+csr_grant san_pkinit bar@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -o "${cachefile}" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8"); then
+ echo "Failed to get a TGT with /get-tgt end-point"
+ exit 2
+fi
+${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+${klist} | grep Addresses:.IPv4:8.8.8.8 ||
+ { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; }
+
+echo "Fetch TGT (for other, w/ lifetime req under max)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_grant san_pkinit bar@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -o "${cachefile}" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8&lifetime=3d"); then
+ echo "Failed to get a TGT with /get-tgt end-point"
+ exit 2
+fi
+${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+if which jq >/dev/null; then
+ if ! ${klistjson} | jq -e '
+ (reduce (.tickets[0]|(.Issued,.Expires)|
+ strptime("%b %e %H:%M:%S %Y")|mktime) as $t
+ (0; if .==0 then $t else $t - . end) / 86400) | floor |
+ . == 3'; then
+ echo "Incorrect lifetime"
+ exit 2
+ fi
+fi
+
+echo "Fetch TGT (for other, w/ lifetime req over max)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_grant san_pkinit bar@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -o "${cachefile}" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8&lifetime=10d"); then
+ echo "Failed to get a TGT with /get-tgt end-point"
+ exit 2
+fi
+${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+if which jq >/dev/null; then
+ if ! ${klistjson} | jq -e '
+ (.tickets[0].Issued | strptime("%b %e %H:%M:%S %Y")|mktime) as $iat
+ | (.tickets[0].Expires | strptime("%b %e %H:%M:%S %Y")|mktime) as $exp
+ | (($exp - $iat) / 86400) as $life_days
+ | ($life_days > 4 and $life_days <= 5)'; then
+ echo "Incorrect lifetime"
+ exit 2
+ fi
+fi
+
+echo "Fetch TGT (for other, w/ lifetime req under max)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_grant san_pkinit bar@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -o "${cachefile}" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8&address=8.9.10.11&address=11.11.11.11&address=12.12.12.12&lifetime=5d"); then
+ echo "Failed to get a TGT with /get-tgt end-point"
+ exit 2
+fi
+${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+if which jq >/dev/null; then
+ if ! ${klistjson} | jq -e '
+ (reduce (.tickets[0]|(.Issued,.Expires)|
+ strptime("%b %e %H:%M:%S %Y")|mktime) as $t
+ (0; if .==0 then $t else $t - . end) / 86400) |
+ . >= 4'; then
+ echo "Failed to get a TGT with /get-tgt end-point with addresses"
+ exit 2
+ fi
+fi
+
+echo "Fetch TGTs (batch, authz fail)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_revoke
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+rm -f "${cachefile}.json"
+if (set -vx;
+ curl -o "${cachefile}.json" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgts?cname=bar@${R}&cname=baz@${R}"); then
+ # 200 Ok is not a problem. We have to check that the result is sane.
+ true
+else
+ if grep ccache "${cachefile}.json"; then
+ echo "Got TGTs with /get-tgts end-point that should have been denied"
+ exit 2;
+ fi
+ if ! grep error_code "${cachefile}.json" > /dev/null; then
+ cat "${cachefile}.json"
+ echo "Request failed w/o error information"
+ exit 2;
+ fi
+fi
+cat "${cachefile}.json"
+if grep ccache "${cachefile}.json"; then
+ echo "Got TGTs with /get-tgts end-point that should have been denied"
+ exit 2;
+fi
+
+echo "Fetch TGTs (batch, partial authz with IPC authorizer)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_revoke
+csr_grant san_pkinit bar@${R} foo@${R}
+csr_grant san_pkinit baz@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -vvvo "${cachefile}.json" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgts?cname=bar@${R}&cname=raz@${R}&cname=baz@${R}"); then
+ echo "Failed to get TGTs batch including non-existent principal"
+ exit 2
+fi
+if which jq >/dev/null; then
+ set -vx
+ jq -e . "${cachefile}.json" > /dev/null ||
+ { echo "/get-tgts produced non-JSON"; exit 2; }
+ jq -es '.[]|select(.name|startswith("raz@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null ||
+ { echo "No error was reported for raz@${R}!"; exit 2; }
+ jq -es '.[]|select(.name|startswith("raz@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null ||
+ { echo "Non-empty ccache included for raz@${R}!"; exit 2; }
+
+ # Check bar@$R's tickets:
+ jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+
+ # Check baz@$R's tickets:
+ jq -r 'select(.name|startswith("baz@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p baz@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+fi
+
+echo "Fetch TGTs (batch, partial authz)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_revoke
+csr_grant san_pkinit bar@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -vvvo "${cachefile}.json" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgts?cname=not@${R}&cname=bar@${R}&cname=baz@${R}"); then
+ echo "Failed to get TGTs batch including non-existent principal"
+ exit 2
+fi
+if which jq >/dev/null; then
+ set -vx
+ jq -e . "${cachefile}.json" > /dev/null ||
+ { echo "/get-tgts produced non-JSON"; exit 2; }
+ jq -es '.[]|select(.name|startswith("not@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null ||
+ { echo "No error was reported for not@${R}!"; exit 2; }
+ jq -es '.[]|select(.name|startswith("not@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null ||
+ { echo "Non-empty ccache included for not@${R}!"; exit 2; }
+ jq -es '.[]|select(.name|startswith("baz@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null ||
+ { echo "No error was reported for baz@${R}!"; exit 2; }
+ jq -es '.[]|select(.name|startswith("baz@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null ||
+ { echo "Non-empty ccache included for baz@${R}!"; exit 2; }
+
+ # Check bar@$R's tickets:
+ jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+fi
+
+echo "Fetch TGTs (batch, authz pass)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_grant san_pkinit bar@${R} foo@${R}
+csr_grant san_pkinit baz@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -vvvo "${cachefile}.json" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgts?cname=bar@${R}&cname=baz@${R}"); then
+ echo "Failed to get TGTs batch"
+ exit 2
+fi
+if which jq >/dev/null; then
+ jq -e . "${cachefile}.json" > /dev/null ||
+ { echo "/get-tgts produced non-JSON"; exit 2; }
+
+ # Check bar@$R's tickets:
+ jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+
+ # Check baz@$R's tickets:
+ jq -r 'select(.name|startswith("baz@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p baz@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+fi
+
+echo "Fetch TGTs (batch, authz pass, one non-existent principal)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_grant san_pkinit bar@${R} foo@${R}
+csr_grant san_pkinit baz@${R} foo@${R}
+csr_grant san_pkinit not@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -vvvo "${cachefile}.json" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgts?cname=not@${R}&cname=bar@${R}&cname=baz@${R}"); then
+ echo "Failed to get TGTs batch including non-existent principal"
+ exit 2
+fi
+if which jq >/dev/null; then
+ set -vx
+ jq -e . "${cachefile}.json" > /dev/null ||
+ { echo "/get-tgts produced non-JSON"; exit 2; }
+ jq -es '.[]|select(.name|startswith("not@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null ||
+ { echo "No error was reported for not@${R}!"; exit 2; }
+
+ # Check bar@$R's tickets:
+ jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+
+ # Check baz@$R's tickets:
+ jq -r 'select(.name|startswith("baz@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p baz@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+fi
+
+echo "killing bx509d (${bx509pid})"
+sh ${leaks_kill} bx509d $bx509pid || ec=1
+
+echo "Starting bx509d (csrf-protection-type=GET-with-token, POST-with-header)"
+${bx509d} --csrf-protection-type=GET-with-token \
+ --csrf-protection-type=POST-with-header --daemon || {
+ echo "bx509 failed to start"
+ exit 2
+}
+bx509pid=`getpid bx509d`
+
+${kinit} -kt $ukeytab foo@${R} || exit 1
+$klist || { echo "failed to kinit"; exit 2; }
+
+echo "Fetching a trivial user certificate (GET with CSRF token)"
+csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx; get_with_token get-cert '' -o "${objdir}/trivial.pem"); then
+ $hxtool print --content "FILE:${objdir}/trivial.pem"
+ if $hxtool acert --end-entity \
+ --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \
+ -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ else
+ echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)'
+ exit 1
+ fi
+ if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \
+ --has-private-key "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ fi
+else
+ echo 'Failed to get a certificate!'
+ exit 1
+fi
+
+echo "Fetching a trivial user certificate (POST with X-CSRF header, no token)"
+# Encode the CSR in base64, then URL-encode it
+csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx; get_cert '' -H 'X-CSRF: junk' -X POST -sf -o "${objdir}/trivial.pem"); then
+ $hxtool print --content "FILE:${objdir}/trivial.pem"
+ if $hxtool acert --end-entity \
+ --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \
+ -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ else
+ echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)'
+ exit 1
+ fi
+ if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \
+ --has-private-key "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ fi
+else
+ echo 'Failed to get a certificate!'
+ exit 1
+fi
+
+echo "Fetch negotiate token (pre-test)"
+# Do what /bnegotiate does, roughly, prior to testing /bnegotiate
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --key=PEM-FILE:"${objdir}/k.pem" "${objdir}/req" ||
+ { echo "Failed to make a CSR"; exit 2; }
+$test_kdc_ca -a bx509 -A foo@${R} PKCS10:${objdir}/req \
+ PEM-FILE:${objdir}/pkinit-test.pem ||
+ { echo "Trivial offline CA test failed (CA)"; exit 2; }
+cat ${objdir}/k.pem >> ${objdir}/pkinit-test.pem
+${kinit} -C PEM-FILE:${objdir}/pkinit-test.pem foo@${R} ||
+ { echo "Trivial offline CA test failed (PKINIT)"; exit 2; }
+${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Trivial offline CA test failed (TGS)"; exit 2; }
+KRB5CCNAME=$cache $gsstoken HTTP@$server | KRB5_KTNAME="$keytab" $gsstoken -r ||
+ { echo "Trivial offline CA test failed (gss-token)"; exit 2; }
+
+# Check that we get up to three tixaddrs k/v in the log
+grep 'REQ.*wrongaddr=true' ${objdir}/messages.log |
+ grep 'tixaddrs=IPv4:11.11.11.11' ||
+ { echo "KDC not warning about requests from wrong address"; exit 2; }
+
+echo "Fetching a Negotiate token"
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+csr=
+if (set -vx;
+ get_with_token get-negotiate-token "target=HTTP%40${server}" -o "${objdir}/negotiate-token"); then
+ # bx509 sends us a token w/o a newline for now; we add one because
+ # gss-token expects it.
+ test -s negotiate-token && echo >> negotiate-token
+ if test -s negotiate-token && KRB5_KTNAME="$keytab" $gsstoken -Nr < negotiate-token; then
+ echo 'Successfully obtained a Negotiate token!'
+ else
+ echo 'Failed to get a Negotiate token (got an unacceptable token)!'
+ exit 1
+ fi
+else
+ echo 'Failed to get a Negotiate token!'
+ exit 1
+fi
+
+referer=https://${otherserver}/blah
+redirect=$(${rkvis} -h https://${otherserver}/blah?q=whatever)
+if (set -vx;
+ curl -o negotiate-token -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/bnegotiate?target=HTTP%40${server}&redirect=${redirect}"); then
+ echo "Error: /bnegotiate with target and redirect succeeded"
+ exit 1
+fi
+
+if (set -vx;
+ curl -o negotiate-token -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then
+ echo "Error: /bnegotiate with redirect but no Referer succeeded"
+ exit 1
+fi
+
+referer=http://${otherserver}/blah
+redirect=$(${rkvis} -h http://${otherserver}/blah?q=whatever)
+if (set -vx;
+ curl -gsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ -H "Referer: $referer" \
+ "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then
+ echo "Error: redirect for non-https referer"
+ exit 1
+fi
+
+referer=https://${otherserver}/blah
+redirect=$(${rkvis} -h https://${otherserver}/blah?q=whatever)
+if (set -vx;
+ curl -gfs -D curlheaders \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ -H "Referer: $referer" \
+ "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then
+ read junk code junk < curlheaders
+ if test "$code" = 307; then
+ echo "Got a proper redirect"
+ else
+ echo "Error: unexpected status code $code (wanted 307)"
+ fi
+else
+ echo "Error: no redirect"
+ exit 1
+fi
+
+echo "killing kdc (${kdcpid}) and bx509d (${bx509pid}) and test_csr_authorizer (${test_csr_authorizer_pid})"
+sh ${leaks_kill} kdc $kdcpid || ec=1
+sh ${leaks_kill} bx509d $bx509pid || ec=1
+sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-canon.in b/third_party/heimdal/tests/kdc/check-canon.in
new file mode 100644
index 0000000..18b83a9
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-canon.in
@@ -0,0 +1,210 @@
+#!/bin/sh
+#
+# Copyright (c) 2011, Secure Endpoints Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+# (krb5_kt_get_entry() is tested in another test)
+${have_db} || exit 77
+
+R1=TEST.H5L.SE
+R2=TEST2.H5L.SE
+R3=TEST3.H5L.SE
+
+port=@port@
+
+kadmin="${kadmin} -l -r ${R1}"
+kdc="${kdc} --addresses=localhost -P $port"
+
+cache="FILE:${objdir}/cache.krb5"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist="${klist} -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+
+KRB5_CONFIG="${objdir}/krb5-canon.conf"
+export KRB5_CONFIG
+
+testfailed="echo test failed; ${klist}; exit 1"
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo "Creating database"
+initflags="init --realm-max-ticket-life=1day --realm-max-renewable-life=1month"
+
+${kadmin} ${initflags} ${R1} || exit 1
+${kadmin} ${initflags} ${R2} || exit 1
+${kadmin} ${initflags} ${R3} || exit 1
+
+${kadmin} add -p foo --use-defaults foo@${R1} || exit 1
+
+${kadmin} add -p cross1 --use-defaults krbtgt/${R1}@${R2} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R2}@${R1} || exit 1
+${kadmin} add -p cross3 --use-defaults krbtgt/${R3}@${R1} || exit 1
+${kadmin} add -p cross4 --use-defaults krbtgt/${R1}@${R3} || exit 1
+${kadmin} add -p cross5 --use-defaults krbtgt/${R3}@${R2} || exit 1
+${kadmin} add -p cross6 --use-defaults krbtgt/${R2}@${R3} || exit 1
+
+${kadmin} add -p foo --use-defaults host/t1@${R1} || exit 1
+${kadmin} add -p foo --use-defaults host/t2@${R2} || exit 1
+${kadmin} add -p foo --use-defaults host/t3@${R3} || exit 1
+${kadmin} add -p foo --use-defaults host/t11.test1.h5l.se@${R1} || exit 1
+${kadmin} add -p foo --use-defaults host/t12.test1.h5l.se@${R2} || exit 1
+${kadmin} add -p foo --use-defaults host/t22.test2.h5l.se@${R2} || exit 1
+${kadmin} add -p foo --use-defaults host/t23.test2.h5l.se@${R3} || exit 1
+${kadmin} add -p foo --use-defaults host/t33.test3.h5l.se@${R3} || exit 1
+
+
+echo "Doing database check"
+${kadmin} check ${R1} || exit 1
+${kadmin} check ${R2} || exit 1
+${kadmin} check ${R3} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo "Starting kdc" ; > messages.log
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+
+ec=0
+
+echo "Getting client initial tickets";
+${kinit} --password-file=${objdir}/foopassword foo@${R1} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "get service tickets (success)"
+for host in t1 t2 t3 t11 t12 t22 t33 ; do
+ echo " $host"
+ ${kgetcred} --name-type=SRV_HST host $host || { ec=1 ; eval "${testfailed}"; }
+done
+echo "get service tickets (failure)"
+for host in t23 ; do
+ echo " $host"
+ ${kgetcred} --name-type=SRV_HST host $host 2>/dev/null && { ec=1 ; eval "${testfailed}"; }
+done
+
+echo "check result"
+${klist} | grep 'host/t1@$' > /dev/null ||
+ { ec=1 ; echo "t1 referral entry not present"; eval "${testfailed}"; }
+${klist} | grep "host/t1@${R1}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t1 entry not present"; eval "${testfailed}"; }
+${klist} | grep 'host/t2@$' > /dev/null ||
+ { ec=1 ; echo "t2 referral entry not present"; eval "${testfailed}"; }
+${klist} | grep "host/t2@${R2}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t2 entry not present"; eval "${testfailed}"; }
+${klist} | grep 'host/t3@$' > /dev/null ||
+ { ec=1 ; echo "t3 referral entry not present"; eval "${testfailed}"; }
+${klist} | grep "host/t3@${R3}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t3 entry not present"; eval "${testfailed}"; }
+${klist} | grep 'host/t11@$' > /dev/null ||
+ { ec=1 ; echo "t11 referral entry not present"; eval "${testfailed}"; }
+${klist} | grep "host/t11.test1.h5l.se@${R1}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t11 entry not present"; eval "${testfailed}"; }
+${klist} | grep 'host/t12@$' > /dev/null ||
+ { ec=1 ; echo "t12 referral entry not present"; eval "${testfailed}"; }
+${klist} | grep "host/t12.test1.h5l.se@${R2}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t12 entry not present"; eval "${testfailed}"; }
+${klist} | grep 'host/t22@$' > /dev/null ||
+ { ec=1 ; echo "t22 referral entry not present"; eval "${testfailed}"; }
+${klist} | grep "host/t22.test2.h5l.se@${R2}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t22 entry not present"; eval "${testfailed}"; }
+${klist} | grep 'host/t33@$' > /dev/null ||
+ { ec=1 ; echo "t33 referral entry not present"; eval "${testfailed}"; }
+${klist} | grep "host/t33.test3.h5l.se@${R3}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t33 entry not present"; eval "${testfailed}"; }
+
+
+${kdestroy}
+
+if false; then
+
+ # This may not be portable. It'd be nice to be able to set more of the
+ # resolver configuration via the environment!
+ LOCALDOMAIN=test1.h5l.se
+ export LOCALDOMAIN
+ KRB5_CONFIG="${objdir}/krb5-canon2.conf"
+ export KRB5_CONFIG
+
+ echo "Getting client initial tickets (round 2)";
+ ${kinit} --password-file=${objdir}/foopassword foo@${R1} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+ echo "get service tickets (success)"
+ for host in t1 t2 t3 t11 ; do
+ echo " $host"
+ ${kgetcred} --name-type=SRV_HST host $host || { ec=1 ; eval "${testfailed}"; }
+ done
+ echo "get service tickets (failure)"
+ for host in t12 t22 t23 t33 ; do
+ echo " $host"
+ ${kgetcred} --name-type=SRV_HST host $host 2> /dev/null &&
+ { ec=1 ; eval "${testfailed}"; }
+ done
+
+ echo "check result"
+ ${klist} | grep 'host/t1@$' > /dev/null ||
+ { ec=1 ; echo "t1 referral entry not present"; eval "${testfailed}"; }
+ ${klist} | grep "host/t1@${R1}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t1 entry not present"; eval "${testfailed}"; }
+ ${klist} | grep 'host/t2@$' > /dev/null ||
+ { ec=1 ; echo "t2 referral entry not present"; eval "${testfailed}"; }
+ ${klist} | grep "host/t2@${R2}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t2 entry not present"; eval "${testfailed}"; }
+ ${klist} | grep 'host/t3@$' > /dev/null ||
+ { ec=1 ; echo "t3 referral entry not present"; eval "${testfailed}"; }
+ ${klist} | grep "host/t3@${R3}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t3 entry not present"; eval "${testfailed}"; }
+ ${klist} | grep 'host/t11@$' > /dev/null ||
+ { ec=1 ; echo "t11 referral entry not present"; eval "${testfailed}"; }
+ ${klist} | grep "host/t11.test1.h5l.se@${R1}" > /dev/null ||
+ { ec=1 ; echo "canonicalized t11 entry not present"; eval "${testfailed}"; }
+
+
+ ${kdestroy}
+fi
+
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-cc.in b/third_party/heimdal/tests/kdc/check-cc.in
new file mode 100644
index 0000000..46e846a
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-cc.in
@@ -0,0 +1,203 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+unset KRB5CCNAME
+
+testfailed="echo test failed; exit 1"
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+
+port=@port@
+pwport=@pwport@
+
+kinit="${kinit} --password-file=${objdir}/foopassword ${afs_no_afslog}"
+kdestroy="${kdestroy} ${afs_no_unlog}"
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+
+server=host/datan.test.h5l.se
+cache="FILE:${objdir}/cache.krb5"
+keytabfile=${objdir}/server.keytab
+keytab="FILE:${keytabfile}"
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+${kadmin} add -p foo --use-defaults bar@${R} || exit 1
+${kadmin} add -p kaka --use-defaults ${server}@${R} || exit 1
+${kadmin} ext -k ${keytab} ${server}@${R} || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo Starting kdc ; > messages.log
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+echo Starting kcm ; > messages.log
+${kcm} -s ${objdir} --detach || { echo "kcm failed to start"; cat messages.log; exit 1; }
+kcmpid=`getpid kcm`
+
+HEIM_IPC_DIR=${objdir}
+export HEIM_IPC_DIR
+
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+
+ec=0
+
+export KRB5CCNAME=SCC:${objdir}/sdb
+
+${kswitch} -p foo@${R} 2>/dev/null && ${kdestroy}
+${kswitch} -p foo@${R} 2>/dev/null && ${kdestroy}
+${kswitch} -p bar@${R} 2>/dev/null && ${kdestroy}
+${kswitch} -p bar@${R} 2>/dev/null && ${kdestroy}
+
+echo "getting default tickets"; > messages.log
+${kinit} foo@${R} || { ec=1 ; eval "${testfailed}"; }
+${kswitch} -p foo@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@ >/dev/null || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "getting both tickets"; > messages.log
+${kinit} -c ${KRB5CCNAME}:1 foo@${R} || { ec=1 ; eval "${testfailed}"; }
+${kinit} -c ${KRB5CCNAME}:2 bar@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "switch foo"
+${kswitch} -p foo@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} | head -2 | grep foo@ >/dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@ >/dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep bar@ >/dev/null || { ec=1 ; eval "${testfailed}"; }
+echo "switch bar"
+${kswitch} -p bar@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} | head -2 | grep bar@ >/dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@ >/dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep bar@ >/dev/null || { ec=1 ; eval "${testfailed}"; }
+echo "delete bar"
+${kdestroy}
+echo "check that bar is gone"
+${klist} -l | grep bar@ >/dev/null && { ec=1 ; eval "${testfailed}"; }
+echo "check that foo is still there"
+${klist} -l | grep foo@ >/dev/null || { ec=1 ; eval "${testfailed}"; }
+${kswitch} -p foo@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "delete foo"
+${kdestroy} || { ec=1 ; eval "${testfailed}"; }
+echo "check that foo is gone"
+${klist} -l | grep foo@ >/dev/null && { ec=1 ; eval "${testfailed}"; }
+echo "check that bar is gone"
+${klist} -l | grep bar@ >/dev/null && { ec=1 ; eval "${testfailed}"; }
+
+echo "getting tickets (KCM)"; > messages.log
+KRB5_CONFIG="${objdir}/krb5-kcm.conf"
+export KRB5_CONFIG
+unset KRB5CCNAME
+${kinit} --default-for-principal foo@${R}
+${kinit} --default-for-principal bar@${R}
+${kinit} bar@${R}
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -c KCM: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+KRB5CCNAME=KCM: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+if [ -n "$BASH_VERSION" ]; then
+ ${klist} -c KCM:${UID} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+ ${klist} -c KCM:${UID}: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+ KRB5CCNAME=KCM:${UID} ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+ KRB5CCNAME=KCM:${UID}: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+fi
+${kdestroy} -A
+${klist} 2>/dev/null && { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep bar@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${kinit} bar@${R}
+${kinit} --default-for-principal foo@${R}
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -c KCM: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+KRB5CCNAME=KCM: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${kdestroy} -A
+
+echo "getting tickets (DIR)"; > messages.log
+KRB5_CONFIG="${objdir}/krb5-cccol.conf"
+export KRB5_CONFIG
+unset KRB5CCNAME
+rm -rf ${objdir}/kt ${objdir}/cc_dir
+mkdir ${objdir}/cc_dir || { ec=1 ; eval "${testfailed}"; }
+${kinit} --default-for-principal foo@${R} || { ec=1 ; eval "${testfailed}"; }
+${kinit} --default-for-principal --no-change-default bar@${R} || { ec=1 ; eval "${testfailed}"; }
+primary=`cat ${objdir}/cc_dir/primary`
+[ "x$primary" = xtkt.foo@${R} ] || { ec=1 ; eval "${testfailed}"; }
+${klist} -l |
+ grep "foo@TEST.H5L.SE.*FILE:${objdir}/cc_dir/tkt.foo@TEST.H5L.SE" > /dev/null ||
+ { ec=1 ; eval "${testfailed}"; }
+${klist} -l |
+ grep "bar@TEST.H5L.SE.*FILE:${objdir}/cc_dir/tkt.bar@TEST.H5L.SE" > /dev/null ||
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "killing kcm (${kcmpid})"
+sh ${leaks_kill} kcm $kcmpid || exit 1
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-delegation.in b/third_party/heimdal/tests/kdc/check-delegation.in
new file mode 100644
index 0000000..fdff0f6
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-delegation.in
@@ -0,0 +1,152 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+R2=TEST2.H5L.SE
+R3=TEST3.H5L.SE
+R4=TEST4.H5L.SE
+
+port=@port@
+
+kadmin="${kadmin} -l -r ${R}"
+kdc="${kdc} --addresses=localhost -P $port"
+
+server=host/datan.test4.h5l.se@TEST4.H5L.ORG
+cache="FILE:${objdir}/cache.krb5"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist="${klist} -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+testfailed="echo test failed; ${klist} -v ; exit 1"
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+initflags="init --realm-max-ticket-life=1day --realm-max-renewable-life=1month"
+
+${kadmin} ${initflags} ${R} || exit 1
+${kadmin} ${initflags} ${R2} || exit 1
+${kadmin} ${initflags} ${R3} || exit 1
+${kadmin} ${initflags} ${R4} || exit 1
+
+${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+
+${kadmin} add -p cross1 --use-defaults krbtgt/${R2}@${R} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R3}@${R2} || exit 1
+${kadmin} add -p cross3 --use-defaults krbtgt/${R4}@${R3} || exit 1
+
+${kadmin} modify --attributes=+ok-as-delegate krbtgt/${R2}@${R} || exit 1
+${kadmin} modify --attributes=+ok-as-delegate krbtgt/${R3}@${R2} || exit 1
+
+${kadmin} add -p foo --use-defaults host/server.test3.h5l.se@${R3} || exit 1
+${kadmin} modify --attributes=+ok-as-delegate host/server.test3.h5l.se@${R3} || exit 1
+${kadmin} add -p foo --use-defaults host/noserver.test3.h5l.se@${R3} || exit 1
+
+${kadmin} add -p foo --use-defaults host/server.test4.h5l.se@${R4} || exit 1
+${kadmin} modify --attributes=+ok-as-delegate host/server.test4.h5l.se@${R4} || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+${kadmin} check ${R2} || exit 1
+${kadmin} check ${R3} || exit 1
+${kadmin} check ${R4} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo Starting kdc; > messages.log
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+
+ec=0
+
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "get cross realm manually"
+${kgetcred} krbtgt/${R2}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} krbtgt/${R3}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} krbtgt/${R4}@${R3} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} host/server.test3.h5l.se@${R3} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} host/server.test4.h5l.se@${R4} || { ec=1 ; eval "${testfailed}"; }
+
+
+echo "check result"
+${klist} -v | awk '/Server:.*host.server.test3/{c=8}{if(c-->0){print}}' | grep 'Ticket flags:.*ok-as-delegate' > /dev/null || \
+ { ec=1 ; echo "server.test3 failed"; eval "${testfailed}"; }
+${klist} -v | awk '/Server:.*host.noserver.test3/{c=8}{if(c-->0){print}}' | grep 'Ticket flags:.*ok-as-delegate' 2> /dev/null && \
+ { ec=1 ; echo "noserver.test3 failed"; eval "${testfailed}"; }
+${klist} -v | awk '/Server:.*host.server.test4/{c=8}{if(c-->0){print}}' | grep 'Ticket flags:.*ok-as-delegate' 2> /dev/null && \
+ { ec=1 ; echo "server.test4 failed" ; eval "${testfailed}"; }
+
+${kdestroy}
+
+#echo "Getting client initial tickets"; > messages.log
+#${kinit} --password-file=${objdir}/foopassword foo@${R} || \
+# { ec=1 ; eval "${testfailed}"; }
+#
+#echo "get cross realm automagicly"
+#${kgetcred} host/server.test4.h5l.se@${R4} || { ec=1 ; eval "${testfailed}"; }
+#
+#echo "check result"
+#${klist} -v | grep -A8 -e 'Server:.*server.test4' | grep 'Ticket flags:.*ok-as-delegate' && { ec=1 ; eval "${testfailed}"; }
+#
+#${kdestroy}
+
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-des.in b/third_party/heimdal/tests/kdc/check-des.in
new file mode 100644
index 0000000..144613d
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-des.in
@@ -0,0 +1,155 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+R2=TEST2.H5L.SE
+
+port=@port@
+
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+
+afsserver=afs/test.h5l.se
+hostserver=host/server.test.h5l.se
+cache="FILE:${objdir}/cache.krb5"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist="${klist} -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R2} || exit 1
+
+${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
+
+${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+${kadmin} add -p kaka --use-defaults ${afsserver}@${R} || exit 1
+${kadmin} add -p kaka --use-defaults ${hostserver}@${R} || exit 1
+${kadmin} add_enctype -r ${afsserver}@${R} des-cbc-crc || exit 1
+${kadmin} add_enctype -r ${hostserver}@${R} des-cbc-crc || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo Starting kdc; > messages.log
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+
+ec=0
+
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting non des tickets (afs)"; > messages.log
+${kgetcred} ${afsserver}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} -v | grep des-cbc-crc > /dev/null && { ec=1 ; eval "${testfailed}"; }
+echo "Getting non des tickets (host/)"; > messages.log
+${kgetcred} ${hostserver}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} -v | grep des-cbc-crc > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting des tickets (fail test)"; > messages.log
+${kgetcred} -e des-cbc-crc ${hostserver}@${R} 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting non des tickets"; > messages.log
+${kgetcred} ${afsserver}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} -v | grep des-cbc-crc > /dev/null && { ec=1 ; eval "${testfailed}"; }
+
+
+KRB5_CONFIG="${objdir}/krb5-weak.conf"
+
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Getting non des tickets (host/), failure test"; > messages.log
+${kgetcred} -e des-cbc-crc ${hostserver}@${R} 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+${klist} -v | grep des-cbc-crc > /dev/null && { ec=1 ; eval "${testfailed}"; }
+
+echo "Getting des tickets (afs)"; > messages.log
+${kgetcred} -e des-cbc-crc ${afsserver}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} -v | grep des-cbc-crc > /dev/null || { ec=1 ; eval "${testfailed}"; }
+
+${kdestroy}
+
+
+
+${kdestroy}
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-digest.in b/third_party/heimdal/tests/kdc/check-digest.in
new file mode 100644
index 0000000..d934f4e
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-digest.in
@@ -0,0 +1,291 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+srcdir="@srcdir@"
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+
+port=@port@
+
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+
+server=host/datan.test.h5l.se
+cache="FILE:${objdir}/cache.krb5"
+ocache="FILE:${objdir}/ocache.krb5"
+keytabfile=${objdir}/server.keytab
+keytab="FILE:${keytabfile}"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist="${klist} -c $cache"
+kdigest="${kdigest} --ccache=$cache"
+
+username=foo
+userpassword=digestpassword
+
+password=foobarbaz
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} add -p $userpassword --use-defaults ${username}@${R} || exit 1
+${kadmin} add -p $password --use-defaults ${server}@${R} || exit 1
+${kadmin} add -p kaka --use-defaults digest/${R}@${R} || exit 1
+${kadmin} modify --attributes=+allow-digest ${server}@${R} || exit 1
+${kadmin} ext -k ${keytab} ${server}@${R} || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+
+echo $password > ${objdir}/foopassword
+
+echo "Starting kdc" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} ${kdc} --detach --testing ||
+ { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap "kill -9 ${kdcpid}; echo signal killing kdc; cat messages.log; exit 1;" EXIT
+
+exitcode=0
+
+echo "Getting digest server tickets"
+${kinit} --password-file=${objdir}/foopassword ${server}@$R || exitcode=1
+${kdigest} digest-server-init \
+ --kerberos-realm=${R} \
+ --type=CHAP > /dev/null || exitcode=1
+
+echo "Trying NTLM"
+
+NTLM_ACCEPTOR_CCACHE="$cache"
+export NTLM_ACCEPTOR_CCACHE
+
+echo "Trying server-init"
+${kdigest} ntlm-server-init \
+ --kerberos-realm=${R} \
+ > sdigest-init || exitcode=1
+
+echo "test_ntlm"
+${test_ntlm} || { echo "test_ntlm failed"; exit 1; }
+
+NTLM_USER_FILE="${srcdir}/ntlm-user-file.txt"
+export NTLM_USER_FILE
+
+echo "test_context --mech-type=ntlm"
+${test_context} --mech-type=ntlm \
+ --client-name=foo@TEST \
+ --name-type=hostbased-service datan@TEST || \
+ { echo "test_context 1 failed"; exit 1; }
+
+${test_context} --mech-type=ntlm \
+ --client-name=foo@TEST \
+ --name-type=hostbased-service datan@host.TEST || \
+ { echo "test_context 2 failed"; exit 1; }
+
+${test_context} --mech-type=ntlm \
+ --client-name=foo@TEST \
+ --name-type=hostbased-service datan@host.test.domain2 || \
+ { echo "test_context 3 failed"; exit 1; }
+
+echo "Trying SL in NTLM"
+
+
+for type in \
+ "" \
+ "--getverifymic" \
+ "--wrapunwrap" \
+ "--getverifymic --wrapunwrap" \
+ ; do
+
+ echo "Trying NTLM type: ${type}"
+ ${test_context} --mech-type=ntlm ${type} \
+ --client-name=foo@TEST \
+ --name-type=hostbased-service datan@TEST || \
+ { echo "test_context 1 failed"; exit 1; }
+
+done
+
+
+echo "Trying CHAP"
+
+${kdigest} digest-server-init \
+ --kerberos-realm=${R} \
+ --type=CHAP \
+ > sdigest-reply || exitcode=1
+
+snonce=`grep server-nonce= sdigest-reply | cut -f2- -d=`
+identifier=`grep identifier= sdigest-reply | cut -f2- -d=`
+opaque=`grep opaque= sdigest-reply | cut -f2- -d=`
+
+${kdigest} digest-client-request \
+ --type=CHAP \
+ --username="$username" \
+ --password="$userpassword" \
+ --opaque="$opaque" \
+ --server-identifier="$identifier" \
+ --server-nonce="$snonce" \
+ > cdigest-reply || exitcode=1
+
+cresponseData=`grep responseData= cdigest-reply | cut -f2- -d=`
+
+#echo user: $username
+#echo server-nonce: $snonce
+#echo opaqeue: $opaque
+#echo identifier: $identifier
+
+${kdigest} digest-server-request \
+ --kerberos-realm=${R} \
+ --type=CHAP \
+ --username="$username" \
+ --opaque="$opaque" \
+ --client-response="$cresponseData" \
+ --server-identifier="$identifier" \
+ --server-nonce="$snonce" \
+ > s2digest-reply || exitcode=1
+
+status=`grep status= s2digest-reply | cut -f2- -d=`
+
+if test "X$status" = "Xok" ; then
+ echo "CHAP response ok"
+else
+ echo "CHAP response failed"
+ exitcode=1
+fi
+
+cresponseData=`echo $cresponseData | sed 's/..../DEADBEEF/'`
+
+${kdigest} digest-server-request \
+ --kerberos-realm=${R} \
+ --type=CHAP \
+ --username="$username" \
+ --opaque="$opaque" \
+ --client-response="$cresponseData" \
+ --server-identifier="$identifier" \
+ --server-nonce="$snonce" \
+ > s2digest-reply || exitcode=1
+
+status=`grep status= s2digest-reply | cut -f2- -d=`
+
+if test "X$status" = "Xfailed" ; then
+ echo "CHAP response fail as it should"
+else
+ echo "CHAP response succeeded errorously"
+ exitcode=1
+fi
+
+echo "Trying MS-CHAP-V2"
+
+${kdigest} digest-server-init \
+ --kerberos-realm=${R} \
+ --type=MS-CHAP-V2 \
+ > sdigest-reply || exitcode=1
+
+snonce=`grep server-nonce= sdigest-reply | cut -f2- -d=`
+opaque=`grep opaque= sdigest-reply | cut -f2- -d=`
+cnonce="21402324255E262A28295F2B3A337C7E"
+
+echo "MS-CHAP-V2 client request"
+${kdigest} digest-client-request \
+ --type=MS-CHAP-V2 \
+ --username="$username" \
+ --password="$userpassword" \
+ --opaque="$opaque" \
+ --client-nonce="$cnonce" \
+ --server-nonce="$snonce" \
+ > cdigest-reply || exitcode=1
+
+cresponseData=`grep responseData= cdigest-reply | cut -f2- -d=`
+cRsp=`grep AuthenticatorResponse= cdigest-reply | cut -f2- -d=`
+ckey=`grep session-key= cdigest-reply | cut -f2- -d=`
+
+${kdigest} digest-server-request \
+ --kerberos-realm=${R} \
+ --type=MS-CHAP-V2 \
+ --username="$username" \
+ --opaque="$opaque" \
+ --client-response="$cresponseData" \
+ --client-nonce="$cnonce" \
+ --server-nonce="$snonce" \
+ > s2digest-reply || exitcode=1
+
+status=`grep status= s2digest-reply | cut -f2- -d=`
+sRsp=`grep rsp= s2digest-reply | cut -f2- -d=`
+skey=`grep session-key= s2digest-reply | cut -f2- -d=`
+
+if test "X$sRsp" != "X$cRsp" ; then
+ echo "rsp wrong $sRsp != $cRsp"
+ exitcode=1
+fi
+
+if test "X$skey" != "X$ckey" ; then
+ echo "rsp wrong"
+ exitcode=1
+fi
+
+if test "X$status" = "Xok" ; then
+ echo "MS-CHAP-V2 response ok"
+else
+ echo "MS-CHAP-V2 response failed"
+ exitcode=1
+fi
+
+trap "" EXIT
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+exit $exitcode
+
diff --git a/third_party/heimdal/tests/kdc/check-fast.in b/third_party/heimdal/tests/kdc/check-fast.in
new file mode 100644
index 0000000..d1683f2
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-fast.in
@@ -0,0 +1,212 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2011 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+KRB5_CONFIG="${1-${objdir}/krb5.conf}"
+export KRB5_CONFIG
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+
+port=@port@
+
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+
+server=host/datan.test.h5l.se
+cache="FILE:${objdir}/cache.krb5"
+acache="FILE:${objdir}/acache.krb5"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+akinit="${kinit} -c $acache ${afs_no_afslog}"
+klist="${klist} -c $cache"
+aklist="${klist} -c $acache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+${kadmin} add -p foo --use-defaults ${server}@${R} || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+
+echo foo > ${objdir}/foopassword
+echo bar > ${objdir}/barpassword
+
+echo Starting kdc ; > messages.log
+env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap "kill -9 ${kdcpid}; echo signal killing kdc; cat messages.log; exit 1;" EXIT
+
+ec=0
+
+#
+# Check armor ticket
+#
+
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Checking for FAST avail"
+${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
+echo "Getting tickets"; > messages.log
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Listing tickets"; > messages.log
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Acquire host ticket to be used as an ARMOR ticket"; > messages.log
+${akinit} --password-file=${objdir}/foopassword ${server}@${R} >/dev/null|| { exit 1; }
+echo "Checking for FAST avail (in the FAST armor cache)"; > messages.log
+${aklist} --hidden | grep fast_avail > /dev/null || { exit 1; }
+
+#
+# Client tests
+#
+
+echo "Getting client initial tickets with FAST armor ticket"; > messages.log
+${kinit} --fast-armor-cache=${acache} \
+ --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Getting client initial tickets with FAST armor ticket [failure]"; > messages.log
+${kinit} --fast-armor-cache=${acache} \
+ --password-file=${objdir}/barpassword foo@$R 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Checking for FAST avail (in the FAST acquired cache)"; > messages.log
+${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
+
+echo "Getting service ticket"
+${kgetcred} ${server}@${R} || { exit 1; }
+${kdestroy}
+
+#
+# Test GSS-API pre-authentication using SAnon. It will only succeed where there
+# is FAST armor to authenticate the KDC, otherwise it will fail as SAnon does
+# not provide mutual authentication (GSS_C_MUTUAL_FLAG).
+#
+
+for mech in sanon-x25519 spnego ; do
+ echo "Trying ${mech} pre-authentication with FAST armor"; > messages.log
+ ${kinit} --fast-armor-cache=${acache} \
+ --anonymous --gss-mech=${mech} @$R 2>/dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+
+ echo "Getting service ticket"
+ ${kgetcred} ${server}@${R} || { exit 1; }
+ ${kdestroy}
+
+ echo "Trying ${mech} pre-authentication with anonymous FAST armor"; > messages.log
+ ${kinit} --pk-anon-fast-armor \
+ --anonymous --gss-mech=${mech} @$R 2>/dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+
+ echo "Getting service ticket"
+ ${kgetcred} ${server}@${R} || { exit 1; }
+ ${kdestroy}
+
+ echo "Trying ${mech} pre-authentication with no FAST armor"; > messages.log
+ ${kinit} \
+ --anonymous --gss-mech=${mech} @$R 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+done
+
+#
+# Use MIT client tools
+#
+
+if [ -n "$MITKRB5" -a -f "${MITKRB5}/kinit" ] ; then
+ echo "Running MIT FAST tests"
+
+ kinitpty=${objdir}/foopassword.rkpty
+cat > ${kinitpty} <<EOF
+expect Password
+password foo\n
+EOF
+
+ echo "Acquire host ticket"; > messages.log
+ ${rkpty} ${kinitpty} "${MITKRB5}/kinit" -c ${acache} ${server}@${R} >/dev/null|| { exit 1; }
+ (${aklist} | grep ${server} > /dev/null ) || { exit 1; }
+
+ echo "Checking for FAST avail"; > messages.log
+ ${aklist} --hidden | grep fast_avail > /dev/null || { exit 1; }
+
+ echo "Using plain to get a initial ticket"; > messages.log
+ ${rkpty} ${kinitpty} "${MITKRB5}/kinit" -c ${cache} foo@${R} >/dev/null|| { exit 1; }
+ (${klist} | grep foo > /dev/null ) || { exit 1; }
+
+ echo "Using FAST to get a initial ticket"; > messages.log
+ ${rkpty} ${kinitpty} "${MITKRB5}/kinit" -c ${cache} -T ${acache} foo@${R} >/dev/null || { exit 1; }
+ (${klist} | grep foo > /dev/null ) || { exit 1; }
+
+ echo "Checking for FAST avail"; > messages.log
+ ${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
+
+ echo "Getting service ticket"; > messages.log
+ "${MITKRB5}/kvno" -c ${cache} ${server}@${R} || { exit 1; }
+
+fi
+
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-hdb-mitdb.in b/third_party/heimdal/tests/kdc/check-hdb-mitdb.in
new file mode 100644
index 0000000..a241aeb
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-hdb-mitdb.in
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+KRB5_CONFIG="${1-${objdir}/krb5-hdb-mitdb.conf}"
+export KRB5_CONFIG
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+# If there is no ldap support compiled in, disable test
+if ${kdc} --builtin-hdb | grep mit-db > /dev/null ; then
+ :
+else
+ echo "no MIT KDB support"
+ exit 77
+fi
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+
+port=@port@
+
+kadmin="${kadmin} -l -r $R --config-file=${KRB5_CONFIG}"
+kdc="${kdc} --addresses=localhost -P $port"
+
+server=host/datan.test.h5l.se
+cache="FILE:${objdir}/cache.krb5"
+keytabfile=${objdir}/server.keytab
+keytab="FILE:${keytabfile}"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist="${klist} -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Database should exist
+
+${kadmin} ext -k ${keytab} ${server}@${R} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo Starting kdc ; > messages.log
+env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+
+ec=0
+
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting tickets"; > messages.log
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Listing tickets"; > messages.log
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-httpkadmind.in b/third_party/heimdal/tests/kdc/check-httpkadmind.in
new file mode 100644
index 0000000..9707fc1
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-httpkadmind.in
@@ -0,0 +1,842 @@
+#!/bin/sh
+#
+# Copyright (c) 2020 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+if ! which curl > /dev/null; then
+ echo "curl is not available -- not testing httpkadmind"
+ exit 77
+fi
+if ! test -x ${objdir}/../../kdc/httpkadmind; then
+ echo "Configured w/o libmicrohttpd -- not testing httpkadmind"
+ exit 77
+fi
+
+R=TEST.H5L.SE
+domain=test.h5l.se
+
+port=@port@
+admport=@admport@
+admport1=@admport@
+admport2=@admport2@
+restport=@restport@
+restport1=@restport@
+restport2=@restport2@
+
+server=datan.test.h5l.se
+otherserver=other.test.h5l.se
+cache="FILE:${objdir}/cache.krb5"
+cache2="FILE:${objdir}/cache2.krb5"
+admincache="FILE:${objdir}/cache3.krb5"
+keyfile="${hx509_data}/key.der"
+keyfile2="${hx509_data}/key2.der"
+kt=${objdir}/kt
+keytab=FILE:${kt}
+ukt=${objdir}/ukt
+ukeytab=FILE:${ukt}
+
+kdc="${kdc} --addresses=localhost -P $port"
+kadminr="${kadmin} -r $R -a $(uname -n)"
+kadmin="${kadmin} -l -r $R"
+kadmind2="${kadmind} --keytab=${keytab} --detach -p $admport2 --read-only"
+kadmind="${kadmind} --keytab=${keytab} --detach -p $admport"
+httpkadmind2="${httpkadmind} --reverse-proxied -T Negotiate -p $restport2"
+httpkadmind="${httpkadmind} --reverse-proxied -T Negotiate -p $restport1"
+
+kinit2="${kinit} -c $cache2 ${afs_no_afslog}"
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+adminklist="${klist} --hidden -v -c $admincache"
+klist2="${klist} --hidden -v -c $cache2"
+klist="${klist} --hidden -v -c $cache"
+kgetcred2="${kgetcred} -c $cache2"
+kgetcred="${kgetcred} -c $cache"
+kdestroy2="${kdestroy} -c $cache2 ${afs_no_unlog}"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+kx509="${kx509} -c $cache"
+
+KRB5_CONFIG="${objdir}/krb5-httpkadmind.conf"
+export KRB5_CONFIG
+KRB5CCNAME=$cache
+export KRB5CCNAME
+HEIM_PIDFILE_DIR=$objdir
+export HEIM_PIDFILE_DIR
+HEIM_IPC_DIR=$objdir
+export HEIM_IPC_DIR
+
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+rm -f *.pem *.crt *.der
+rm -rf authz_dir
+rm -f extracted_keytab*
+
+mkdir -p authz_dir
+
+> messages.log
+
+# We'll avoid using a KDC for now. For testing /httpkadmind we only need keys
+# for Negotiate tokens, and we'll use ktutil and kimpersonate to make it
+# possible to create and accept those without a KDC.
+
+# grant ext-type value grantee_principal
+grant() {
+ mkdir -p "${objdir}/authz_dir/${3}"
+ touch "${objdir}/authz_dir/${3}/${1}=${2}"
+}
+
+revoke() {
+ rm -rf "${objdir}/authz_dir"
+ mkdir -p "${objdir}/authz_dir"
+}
+
+if set -o|grep 'verbose.*on' > /dev/null ||
+ set -o|grep 'xtrace.*on' > /dev/null; then
+ verbose=-vvv
+else
+ verbose=
+fi
+
+# HTTP curl-opts
+HTTP() {
+ curl -g --resolve ${server}:${restport2}:127.0.0.1 \
+ --resolve ${server}:${restport}:127.0.0.1 \
+ -u: --negotiate $verbose \
+ -D response-headers \
+ "$@"
+}
+
+# get_config QPARAMS curl-opts
+get_config() {
+ url="http://${server}:${restport}/get-config?$1"
+ shift
+ HTTP $verbose "$@" "$url"
+}
+
+check_age() {
+ set -- $(grep -i ^Cache-Control: response-headers)
+ if [ $# -eq 0 ]; then
+ return 1
+ fi
+ shift
+ for param in "$@"; do
+ case "$param" in
+ no-store) true;;
+ max-age=0) return 1;;
+ max-age=*) true;;
+ *) return 1;;
+ esac
+ done
+ return 0;
+}
+
+# get_keytab QPARAMS curl-opts
+get_keytab() {
+ url="http://${server}:${restport}/get-keys?$1"
+ shift
+ HTTP $verbose "$@" "$url"
+}
+
+# get_keytab_POST QPARAMS curl-opts
+get_keytab_POST() {
+ # Curl is awful, so if you don't use -f, you don't get non-zero exit codes on
+ # error responses, but if you do use -f then -D doesn't work. Ugh.
+ #
+ # So first we check that POST w/o CSRF token fails:
+ q=$1
+ shift
+
+ get_keytab "$q" -X POST --data-binary @/dev/null -f "$@" &&
+ { echo "POST succeeded w/o CSRF token!"; return 1; }
+ get_keytab "$q" -X POST --data-binary @/dev/null "$@"
+ grep ^X-CSRF-Token: response-headers >/dev/null || return 1
+ get_keytab "$q" -X POST --data-binary @/dev/null \
+ -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" "$@"
+ grep '^HTTP/1.1 200' response-headers >/dev/null || return $?
+ return 0
+}
+
+get_keytab_POST_redir() {
+ url="http://${server}:${restport}/get-keys?$1"
+ shift
+ HTTP -X POST --data-binary @/dev/null "$@" "$url"
+ grep ^X-CSRF-Token: response-headers >/dev/null ||
+ { echo "POST w/o CSRF token had response w/o CSRF token!"; return 1; }
+ HTTP -X POST --data-binary @/dev/null -f \
+ -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \
+ --location --location-trusted "$@" "$url"
+}
+
+kdcpid=
+httpkadmindpid=
+httpkadmind2pid=
+test_csr_authorizer_pid=
+kadmindpid=
+kadmind2pid=
+cleanup() {
+ test -n "$kdcpid" &&
+ { echo signal killing kdc; kill -9 "$kdcpid"; }
+ test -n "$test_csr_authorizer_pid" &&
+ { echo signal killing test_csr_authorizer; kill -9 "$test_csr_authorizer_pid"; }
+ test -n "$httpkadmindpid" &&
+ { echo signal killing httpkadmind; kill -9 "$httpkadmindpid"; }
+ test -n "$httpkadmind2pid" &&
+ { echo signal killing second httpkadmind; kill -9 "$httpkadmind2pid"; }
+ test -n "$kadmindpid" &&
+ { echo signal killing kadmind; kill -9 "$kadmindpid"; }
+ test -n "$kadmind2pid" &&
+ { echo signal killing kadmind; kill -9 "$kadmind2pid"; }
+}
+trap cleanup EXIT
+
+rm -f extracted_keytab
+
+echo "Creating database"
+rm -f $kt $ukt
+${kadmin} <<EOF || exit 1
+init --realm-max-ticket-life=1day --realm-max-renewable-life=1month ${R}
+add -r --use-defaults foo@${R}
+add -r --use-defaults httpkadmind/admin@${R}
+add -r --use-defaults WELLKNOWN/CSRFTOKEN@${R}
+add -r --use-defaults HTTP/localhost@${R}
+add -r --use-defaults host/xyz.${domain}@${R}
+add -r --use-defaults HTTP/xyz.${domain}@${R}
+add_ns --key-rotation-epoch=-1d --key-rotation-period=5m \
+ --max-ticket-life=1d --max-renewable-life=5d \
+ --attributes= HTTP/ns.${domain}@${R}
+add_ns --key-rotation-epoch=-1d --key-rotation-period=5m \
+ --max-ticket-life=1d --max-renewable-life=5d \
+ --attributes=ok-as-delegate host/.ns2.${domain}@${R}
+add -r --use-defaults HTTP/${server}@${R}
+ext_keytab -r -k $keytab kadmin/admin@${R}
+ext_keytab -r -k $keytab httpkadmind/admin@${R}
+ext_keytab -r -k $keytab HTTP/${server}@${R}
+ext_keytab -r -k $keytab HTTP/localhost@${R}
+add -r --use-defaults HTTP/${otherserver}@${R}
+ext_keytab -r -k $ukeytab foo@${R}
+EOF
+${kdestroy}
+
+# For a while let's not bother with a KDC
+$kimpersonate --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \
+ -c foo@${R} -s HTTP/datan.test.h5l.se@${R} ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+$kimpersonate -A --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \
+ -c foo@${R} -s HTTP/localhost@${R} ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+$klist -t >/dev/null ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+
+echo "Starting test_csr_authorizer"
+${test_csr_authorizer} -A $objdir/authz_dir -S $objdir --server --daemon ||
+ { echo "test_csr_authorizer failed to start"; exit 2; }
+test_csr_authorizer_pid=`getpid test_csr_authorizer`
+ec=0
+
+echo "Starting httpkadmind"
+${httpkadmind} -H $server -H localhost --local -t --daemon ||
+ { echo "httpkadmind failed to start"; exit 2; }
+httpkadmindpid=`getpid httpkadmind`
+ec=0
+
+echo "Checking that concrete principal exists"
+${kadmin} get HTTP/xyz.${domain} > /dev/null ||
+ { echo "Failed to create HTTP/xyz.${domain}"; exit 1; }
+echo "Checking that virtual principal exists"
+${kadmin} get HTTP/foo.ns.${domain} > /dev/null ||
+ { echo "Virtual principals not working"; exit 1; }
+
+hn=xyz.${domain}
+p=HTTP/$hn
+echo "Fetching krb5.conf for $p"
+get_config "princ=$p" -sf -o "${objdir}/extracted_config" ||
+ { echo "Failed to get config for $p"; exit 1; }
+read config < "${objdir}/extracted_config"
+test "$config" = "include /etc/krb5.conf" ||
+ { echo "Got unexpected default config for $p"; exit 1; }
+${kadmin} mod --krb5-config-file="$KRB5_CONFIG" $p ||
+ { echo "Failed to set config for $p"; exit 1; }
+get_config "princ=$p" -sf -o "${objdir}/extracted_config" ||
+ { echo "Failed to get config for $p"; exit 1; }
+cmp "${objdir}/extracted_config" "$KRB5_CONFIG" ||
+ { echo "Got unexpected config for $p"; exit 1; }
+
+hn=xyz.${domain}
+p=HTTP/$hn
+echo "Fetching keytab for concrete principal $p"
+rm -f extracted_keytab*
+grant san_dnsname $hn foo@${R}
+${kadmin} ext_keytab -k extracted_keytab $p ||
+ { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.kadmin extracted_keytab.rest ||
+ { echo "Keytabs for $p don't match!"; exit 1; }
+
+hn=foo.ns.${domain}
+p=HTTP/$hn
+echo "Fetching keytab for virtual principal $p"
+rm -f extracted_keytab*
+grant san_dnsname $hn foo@${R}
+${kadmin} ext_keytab -k extracted_keytab $p ||
+ { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+check_age
+grep -i ^Cache-Control response-headers
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.kadmin extracted_keytab.rest ||
+ { echo "Keytabs for $p don't match!"; exit 1; }
+
+hn1=foo.ns.${domain}
+hn2=foobar.ns.${domain}
+hn3=xyz.${domain}
+p1=HTTP/$hn1
+p2=HTTP/$hn2
+p3=HTTP/$hn3
+echo "Fetching keytabs for more than one principal"
+rm -f extracted_keytab*
+grant san_dnsname $hn1 foo@${R}
+grant san_dnsname $hn2 foo@${R}
+grant san_dnsname $hn3 foo@${R}
+# Note that httpkadmind will first process dNSName q-params, then the spn
+# q-params.
+${kadmin} ext_keytab -k extracted_keytab $p1 ||
+ { echo "Failed to get a keytab for $p1 with kadmin"; exit 1; }
+${kadmin} ext_keytab -k extracted_keytab $p3 ||
+ { echo "Failed to get a keytab for $p3 with kadmin"; exit 1; }
+${kadmin} ext_keytab -k extracted_keytab $p2 ||
+ { echo "Failed to get a keytab for $p2 with kadmin"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
+ { echo "Failed to list keytab for multiple principals"; exit 1; }
+get_keytab "dNSName=${hn1}&spn=${p2}&dNSName=${hn3}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for multiple principals with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.kadmin extracted_keytab.rest ||
+ { echo "Keytabs for $p don't match!"; exit 1; }
+grep $hn1 extracted_keytab.rest > /dev/null ||
+ { echo "Keytab does not include keys for $p1"; exit 1; }
+grep $hn2 extracted_keytab.rest > /dev/null ||
+ { echo "Keytab does not include keys for $p2"; exit 1; }
+grep $hn3 extracted_keytab.rest > /dev/null ||
+ { echo "Keytab does not include keys for $p3"; exit 1; }
+
+p=host/foo.ns.${domain}
+echo "Checking that $p doesn't exist (no namespace for host service)"
+get_keytab "svc=host&dNSName=foo.ns.${domain}" -sf -o "${objdir}/extracted_keytab.rest" &&
+ { echo "Got a keytab for host/foo.ns.${domain} when not namespaced!"; }
+
+echo "Checking that authorization is enforced"
+revoke
+get_keytab "dNSName=xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "Got a keytab for HTTP/xyz.${domain} when not authorized!"; exit 1; }
+get_keytab "dNSName=foo.ns.${domain}" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "Got a keytab for HTTP/foo.ns.${domain} when not authorized!"; exit 1; }
+
+echo "Checking that host service keys are not served"
+hn=xyz.${domain}
+p=host/$hn
+echo "Fetching keytab for virtual principal $p"
+rm -f extracted_keytab*
+grant san_dnsname $hn foo@${R}
+get_keytab "service=host&dNSName=xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "Got a keytab for $p even though it is a host service!"; exit 1; }
+get_keytab "spn=host/xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "Got a keytab for $p even though it is a host service!"; exit 1; }
+revoke
+
+hn=xyz.${domain}
+p=HTTP/$hn
+echo "Checking key rotation for concrete principal $p"
+rm -f extracted_keytab*
+grant san_dnsname $hn foo@${R}
+get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 1 ||
+ { echo "Wrong number of new keys!"; exit 1; }
+get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "GET succeeded for write operation!"; exit 1; }
+get_keytab_POST "dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to rotate keys for $p"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
+ { echo "Keys for $p did not change!"; exit 1; }
+test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 ||
+ { echo "Wrong number of new keys!"; exit 1; }
+
+hn=xyz.${domain}
+p=HTTP/$hn
+echo "Checking key rotation w/ revocation for concrete principal $p"
+rm -f extracted_keytab*
+grant san_dnsname $hn foo@${R}
+get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+get_keytab "dNSName=${hn}&revoke=true" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "GET succeeded for write operation!"; exit 1; }
+get_keytab_POST "dNSName=${hn}&revoke=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
+ { echo "Keys for $p did not change!"; exit 1; }
+test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 1 ||
+ { echo "Wrong number of new keys!"; exit 1; }
+
+hn=abc.${domain}
+p=HTTP/$hn
+echo "Checking concrete principal creation ($p)"
+rm -f extracted_keytab
+grant san_dnsname $hn foo@${R}
+get_keytab "dNSName=${hn}&create=true" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "GET succeeded for write operation!"; exit 1; }
+get_keytab_POST "dNSName=${hn}&create=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+rm -f extracted_keytab
+${kadmin} ext_keytab -k extracted_keytab $p ||
+ { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.kadmin extracted_keytab.rest ||
+ { echo "Keytabs for $p don't match!"; exit 1; }
+
+hn=bar.ns.${domain}
+p=HTTP/$hn
+echo "Checking materialization of virtual principal ($p)"
+rm -f extracted_keytab
+grant san_dnsname $hn foo@${R}
+get_keytab "dNSName=${hn}&materialize=true" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "GET succeeded for write operation!"; exit 1; }
+get_keytab_POST "dNSName=${hn}&materialize=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to materialize and get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+rm -f extracted_keytab
+${kadmin} ext_keytab -k extracted_keytab $p ||
+ { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.kadmin extracted_keytab.rest ||
+ { echo "Keytabs for $p don't match!"; exit 1; }
+
+echo "Starting secondary httpkadmind to test HTTP redirection"
+${httpkadmind2} --primary-server-uri=http://localhost:$restport \
+ -H $server --local --local-read-only -t --daemon ||
+ { echo "httpkadmind failed to start"; exit 2; }
+httpkadmind2pid=`getpid httpkadmind`
+ec=0
+
+hn=def.${domain}
+p=HTTP/$hn
+restport=$restport2
+echo "Checking principal creation at secondary yields redirect"
+rm -f extracted_keytab
+grant san_dnsname $hn foo@${R}
+get_keytab_POST_redir "dNSName=${hn}&create=true" \
+ -s -o "${objdir}/extracted_keytab"
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+rm -f extracted_keytab
+${kadmin} ext_keytab -k extracted_keytab $p ||
+ { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.kadmin extracted_keytab.rest ||
+ { echo "Keytabs for $p don't match!"; exit 1; }
+
+echo "killing httpkadmind (${httpkadmindpid} ${httpkadmind2pid})"
+sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
+sh ${leaks_kill} httpkadmind $httpkadmind2pid || ec=1
+httpkadmindpid=
+httpkadmind2pid=
+test $ec = 1 &&
+ { echo "Error killing httpkadmind instances or memory errors found"; exit 1; }
+
+echo "Starting primary kadmind for testing httpkadmind with remote HDB"
+${kadmind} ||
+ { echo "Read-write kadmind failed to start"; exit 2; }
+kadmindpid=`getpid kadmind`
+echo "Starting secondray (read-only) kadmind for testing httpkadmind with remote HDB"
+${kadmind2} ||
+ { echo "Read-only kadmind failed to start"; exit 2; }
+kadmind2pid=`getpid kadmind`
+
+# Make a ccache for use with kadmin(1)
+$kimpersonate --ticket-flags=initial --ccache=$admincache -k $keytab -t aes128-cts-hmac-sha1-96 \
+ -c httpkadmind/admin@${R} -s kadmin/admin@${R} ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+$adminklist -t >/dev/null ||
+ { echo "failed to setup kimpersonate credentials"; exit 2; }
+
+
+echo "Making PKINIT certs for KDC"
+${hxtool} issue-certificate \
+ --self-signed \
+ --issue-ca \
+ --ca-private-key=FILE:${keyfile} \
+ --subject="CN=CA,DC=test,DC=h5l,DC=se" \
+ --certificate="FILE:ca.crt" || exit 1
+${hxtool} request-create \
+ --subject="CN=kdc,DC=test,DC=h5l,DC=se" \
+ --key=FILE:${keyfile2} \
+ req-kdc.der || exit 1
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-kdc" \
+ --pk-init-principal="krbtgt/TEST.H5L.SE@TEST.H5L.SE" \
+ --req="PKCS10:req-kdc.der" \
+ --certificate="FILE:kdc.crt" || exit 1
+${hxtool} request-create \
+ --subject="CN=bar,DC=test,DC=h5l,DC=se" \
+ --key=FILE:${keyfile2} \
+ req-pkinit.der ||
+ { echo "Failed to make CSR for PKINIT client cert"; exit 1; }
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --pk-init-principal="host/synthesized.${domain}@$R" \
+ --req="PKCS10:req-pkinit.der" \
+ --lifetime=7d \
+ --certificate="FILE:pkinit-synthetic.crt" ||
+ { echo "Failed to make PKINIT client cert"; exit 1; }
+
+echo "Starting kdc needed for httpkadmind authentication to kadmind"
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+echo "Starting httpkadmind with remote HDBs only"
+restport=$restport1
+${httpkadmind} -H $server -H localhost -t --daemon \
+ --writable-admin-server=$(uname -n):$admport \
+ --read-only-admin-server=$(uname -n):$admport2 \
+ --kadmin-client-name=httpkadmind/admin@${R} \
+ --kadmin-client-keytab=$keytab ||
+ { echo "httpkadmind failed to start"; exit 2; }
+httpkadmindpid=`getpid httpkadmind`
+ec=0
+
+hn=xyz.${domain}
+p=HTTP/$hn
+echo "Fetching keytab for concrete principal $p using remote HDB"
+rm -f extracted_keytab*
+grant san_dnsname $hn httpkadmind/admin@${R}
+KRB5CCNAME=$admincache ${kadmin} ext_keytab -k extracted_keytab $p ||
+ { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+get_keytab "spn=${p}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.kadmin extracted_keytab.rest ||
+ { echo "Keytabs for $p don't match!"; exit 1; }
+
+hn=xyz.${domain}
+p=HTTP/$hn
+echo "Checking key rotation for concrete principal $p using remote HDB"
+rm -f extracted_keytab*
+grant san_dnsname $hn foo@${R}
+get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 1 ||
+ { echo "Wrong number of new keys!"; exit 1; }
+get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "GET succeeded for write operation!"; exit 1; }
+get_keytab_POST "dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to rotate keys for $p"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
+ { echo "Keys for $p did not change!"; exit 1; }
+test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 ||
+ { echo "Wrong number of new keys!"; exit 1; }
+
+sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
+httpkadmindpid=
+
+echo "Starting httpkadmind with local read-only HDB and remote read-write HDB"
+${httpkadmind} -H $server -H localhost -t --daemon \
+ --local-read-only \
+ --writable-admin-server=$(uname -n):$admport \
+ --kadmin-client-name=httpkadmind/admin@${R} \
+ --kadmin-client-keytab=$keytab ||
+ { echo "httpkadmind failed to start"; exit 2; }
+httpkadmindpid=`getpid httpkadmind`
+ec=0
+
+hn=xyz.${domain}
+p=HTTP/$hn
+echo "Fetching keytab for concrete principal $p using local read-only HDB"
+rm -f extracted_keytab*
+grant san_dnsname $hn httpkadmind/admin@${R}
+KRB5CCNAME=$admincache ${kadmin} ext_keytab -k extracted_keytab $p ||
+ { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+get_keytab "spn=${p}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.kadmin extracted_keytab.rest ||
+ { echo "Keytabs for $p don't match!"; exit 1; }
+
+hn=xyz.${domain}
+p=HTTP/$hn
+echo "Checking key rotation for concrete principal $p using local read-only HDB and remote HDB"
+rm -f extracted_keytab*
+grant san_dnsname $hn foo@${R}
+get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to get a keytab for $p with curl"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 2 ||
+ { echo "Wrong number of new keys!"; exit 1; }
+get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
+ { echo "GET succeeded for write operation!"; exit 1; }
+get_keytab_POST "dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to rotate keys for $p"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 ||
+ { echo "Failed to list keytab for $p"; exit 1; }
+cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
+ { echo "Keys for $p did not change!"; exit 1; }
+test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 3 ||
+ { echo "Wrong number of new keys!"; exit 1; }
+
+echo "Checking that host services as clients can self-create"
+hn=synthesized.${domain}
+p=host/$hn
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null &&
+ { echo "Internal error -- $p exists too soon"; exit 1; }
+${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
+ { echo "Failed to kinit with PKINIT client cert"; exit 1; }
+${kgetcred2} HTTP/localhost@$R || echo WAT
+rm -f extracted_keytab*
+KRB5CCNAME=$cache2 \
+get_keytab_POST "spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list > /dev/null ||
+ { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+
+echo "Checking that host services can't get other host service principals"
+hn=nonexistent.${domain}
+p=host/$hn
+KRB5CCNAME=$cache2 \
+get_keytab_POST "spn=$p&create=true" -s -o "${objdir}/extracted_keytab2" &&
+ { echo "Failed to fail to create and extract host keys for other!"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab2" list > /dev/null || true
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null &&
+ { echo "Failed to fail to create and extract host keys for other!"; exit 1; }
+
+echo "Checking that host services can't get keys for themselves and others"
+hn=synthesized.${domain}
+p=host/$hn
+p2=host/nonexistent.${domain}
+${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
+ { echo "Failed to kinit with PKINIT client cert"; exit 1; }
+${kgetcred2} HTTP/localhost@$R || echo WAT
+rm -f extracted_keytab*
+KRB5CCNAME=$cache2 \
+get_keytab_POST "spn=$p&spn=$p2&create=true" -s -o "${objdir}/extracted_keytab" &&
+ { echo "Failed to fail to create and extract host keys for other!"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab2" list > /dev/null || true
+KRB5CCNAME=$admincache ${kadmin} get -s $p2 >/dev/null &&
+ { echo "Failed to fail to create and extract host keys for other!"; exit 1; }
+
+echo "Checking that attributes for new principals can be configured"
+hn=a-particular-hostname.test.h5l.se
+p=host/$hn
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --pk-init-principal="$p@$R" \
+ --req="PKCS10:req-pkinit.der" \
+ --lifetime=7d \
+ --certificate="FILE:pkinit-synthetic.crt" ||
+ { echo "Failed to make PKINIT client cert"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null 2>&1 &&
+ { echo "Internal error -- $p exists too soon"; exit 1; }
+${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
+ { echo "Failed to kinit with PKINIT client cert"; exit 1; }
+${kgetcred2} HTTP/localhost@$R || echo WAT
+rm -f extracted_keytab*
+KRB5CCNAME=$cache2 \
+get_keytab_POST "spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list > /dev/null ||
+ { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get $p |
+ grep 'Attributes:.*ok-as-delegate' > /dev/null ||
+ { echo "Failed to create with configured attributes"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get $p |
+ grep 'Attributes:.*no-auth-data-reqd' > /dev/null ||
+ { echo "Failed to create with configured attributes"; exit 1; }
+
+hn=other-hostname.test.h5l.se
+p=host/$hn
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --pk-init-principal="$p@$R" \
+ --req="PKCS10:req-pkinit.der" \
+ --lifetime=7d \
+ --certificate="FILE:pkinit-synthetic.crt" ||
+ { echo "Failed to make PKINIT client cert"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null 2>&1 &&
+ { echo "Internal error -- $p exists too soon"; exit 1; }
+${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
+ { echo "Failed to kinit with PKINIT client cert"; exit 1; }
+${kgetcred2} HTTP/localhost@$R || echo WAT
+rm -f extracted_keytab*
+KRB5CCNAME=$cache2 \
+get_keytab_POST "spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list > /dev/null ||
+ { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get $p |
+ grep 'Attributes:.*ok-as-delegate' > /dev/null &&
+ { echo "Create with unexpected attributes"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get $p |
+ grep 'Attributes:.*no-auth-data-reqd' > /dev/null &&
+ { echo "Create with unexpected attributes"; exit 1; }
+
+hn=a-server.prod.test.h5l.se
+p=host/$hn
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --pk-init-principal="$p@$R" \
+ --req="PKCS10:req-pkinit.der" \
+ --lifetime=7d \
+ --certificate="FILE:pkinit-synthetic.crt" ||
+ { echo "Failed to make PKINIT client cert"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null 2>&1 &&
+ { echo "Internal error -- $p exists too soon"; exit 1; }
+${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
+ { echo "Failed to kinit with PKINIT client cert"; exit 1; }
+${kgetcred2} HTTP/localhost@$R || echo WAT
+rm -f extracted_keytab*
+KRB5CCNAME=$cache2 \
+get_keytab_POST "spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list > /dev/null ||
+ { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get $p |
+ grep 'Attributes:.*ok-as-delegate' > /dev/null ||
+ { echo "Failed to create with configured attributes"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get $p |
+ grep 'Attributes:.*no-auth-data-reqd' > /dev/null ||
+ { echo "Failed to create with configured attributes"; exit 1; }
+
+hn=a-host.ns2.test.h5l.se
+p=host/$hn
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --pk-init-principal="$p@$R" \
+ --req="PKCS10:req-pkinit.der" \
+ --lifetime=7d \
+ --certificate="FILE:pkinit-synthetic.crt" ||
+ { echo "Failed to make PKINIT client cert"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null 2>&1 &&
+ { echo "Internal error -- $p exists too soon"; exit 1; }
+${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
+ { echo "Failed to kinit with PKINIT client cert"; exit 1; }
+${kgetcred2} HTTP/localhost@$R || echo WAT
+rm -f extracted_keytab*
+KRB5CCNAME=$cache2 \
+get_keytab_POST "spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+${ktutil} -k "${objdir}/extracted_keytab" list > /dev/null ||
+ { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get -s $p >/dev/null ||
+ { echo "Failed to create and extract host keys for self"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get $p |
+ grep 'Attributes:.*ok-as-delegate' > /dev/null ||
+ { echo "Failed to create with namespace attributes"; exit 1; }
+KRB5CCNAME=$admincache ${kadmin} get $p |
+ grep 'Attributes:.*no-auth-data-reqd' > /dev/null &&
+ { echo "Create with unexpected attributes"; exit 1; }
+
+grep 'Internal error' messages.log &&
+ { echo "Internal errors in log"; exit 1; }
+
+sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1
+sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
+sh ${leaks_kill} kadmind $kadmindpid || ec=1
+sh ${leaks_kill} kadmind $kadmind2pid || ec=1
+sh ${leaks_kill} kdc $kdcpid || ec=1
+
+if [ $ec = 0 ]; then
+ trap "" EXIT
+ echo "Success"
+fi
+
+# TODO
+#
+# - implement and test that we can materialize a principal yet leave it with
+# virtual keys
+# - test new key delay? this one is tricky
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-iprop.in b/third_party/heimdal/tests/kdc/check-iprop.in
new file mode 100644
index 0000000..5243793
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-iprop.in
@@ -0,0 +1,611 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+db_type=@db_type@
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+
+# Don't run this test in AFS, since it lacks support for AF_UNIX
+expr "X`/bin/pwd || pwd`" : "X/afs/.*" > /dev/null 2>/dev/null && exit 77
+
+R=TEST.H5L.SE
+
+port=@port@
+ipropport=@ipropport@
+ipropport2=@ipropport2@
+
+cache="FILE:${objdir}/cache.krb5"
+keytabfile=${objdir}/iprop.keytab
+keytab="FILE:${keytabfile}"
+
+kdc="${kdc} --addresses=localhost -P $port"
+kadmin="${kadmin} -r $R"
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+
+# We'll test iprop, and in particular, hierarchical iprop. This means we'll
+# have a setup like:
+#
+# ipropd-master -> ipropd-slave -> 2nd ipropd-master -> 2nd ipropd-slave
+
+# Waiting for incremental propagation is inherently difficult because we don't
+# have a way for ipropd-slave to signal this script that it has received
+# updates. Well, it does have a way to signal a possible ipropd-master for
+# hierarchical iprop, but we don't have a way to get that signal here.
+#
+# FIXME: Add a private interface for async waiting for iprop.
+#
+# What we do is we have a set of utility functions:
+#
+# - get_iprop_ver [N] -> checks that N (default to 1) ops have made it over
+# - get_iprop_ver2 [N] -> same, but for second ipropd-slave instance
+#
+# - wait_for -> repeat a command until it succeeds or too many tries
+# - wait_for_slave [N] -> wait for N ops to make it over (calls get_iprop_ver)
+# - wait_for_slave2 [N] -> same, but for second ipropd-slave instance
+#
+# In particular the wait_for* functions busy-wait for a max amount of time,
+# with sleeps in between.
+#
+# NOTE: get_iprop_ver and get_iprop_ver2 keep hidden state.
+#
+# When first called, get_iprop_ver / get_iprop_ver2 save the current version
+# numbers. Thereafter they check that N ops have been received.
+#
+# It is critical to account for every incremental op via get_iprop_ver /
+# get_iprop_ver2, or wait_for_slave / wait_for_slave2, otherwise this test will
+# be racy and will have spurious failures!
+#
+# The pattern should be something like this:
+#
+# echo "Add host"
+# ${kadmin} -l add --random-key --use-defaults host/foo@${R} || exit 1
+# wait_for_slave
+# ^^^^^^^^^^^^^^
+# waits for 1 operation
+#
+# or
+#
+# echo "Rollover host keys"
+# ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
+# ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
+# ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
+# wait_for_slave 3
+# ^^^^^^^^^^^^^^^^
+# waits for the three operations
+#
+# So though all operations must be accounted for, they need not be accounted
+# one by one.
+
+slave_ver_from_master_old=
+slave_ver_from_master_new=
+slave_ver_old=
+slave_ver_new=
+get_iprop_ver () {
+ min_change=${1:-1}
+ slave_ver_from_master_new=`grep '^iprop/' iprop-stats | head -1 | awk '{print $3}'`
+ slave_ver_new=`grep 'up-to-date with version:' iprop-slave-status | awk '{print $4}'`
+ if [ -z "$slave_ver_from_master_new" -o -z "$slave_ver_new" ]; then
+ return 1
+ fi
+ if [ x"$slave_ver_from_master_new" != x"$slave_ver_new" ]; then
+ return 1
+ fi
+ if [ x"$slave_ver_from_master_old" != x ]; then
+ change=`expr "$slave_ver_from_master_new" - "$slave_ver_from_master_old"`
+ if [ "$change" -lt "$min_change" ]; then
+ return 1
+ fi
+ fi
+ slave_ver_from_master_old=$slave_ver_from_master_new
+ slave_ver_old=$slave_ver_new
+ return 0
+}
+
+slave_ver_from_master_old2=
+slave_ver_from_master_new2=
+slave_ver_old2=
+slave_ver_new2=
+get_iprop_ver2 () {
+ min_change=${1:-1}
+ slave_ver_from_master_new2=`grep '^iprop/' iprop-stats2 | head -1 | awk '{print $3}'`
+ slave_ver_new2=`grep 'up-to-date with version:' iprop-slave-status2 | awk '{print $4}'`
+ if [ -z "$slave_ver_from_master_new2" -o -z "$slave_ver_new2" ]; then
+ return 1
+ fi
+ if [ x"$slave_ver_from_master_new2" != x"$slave_ver_new2" ]; then
+ return 1
+ fi
+ if [ x"$slave_ver_from_master_old2" != x ]; then
+ change=`expr "$slave_ver_from_master_new2" - "$slave_ver_from_master_old2"`
+ if [ "$change" -lt "$min_change" ]; then
+ return 1
+ fi
+ fi
+ slave_ver_from_master_old2=$slave_ver_from_master_new2
+ slave_ver_old2=$slave_ver_new2
+ return 0
+}
+
+waitsec=65
+sleeptime=2
+wait_for () {
+ msg=$1
+ shift
+ t=0
+ while ! "$@"; do
+ sleep $sleeptime;
+ t=`expr $t + $sleeptime`
+ if [ $t -gt $waitsec ]; then
+ echo "Waited too long for $msg"
+ exit 1
+ fi
+ done
+ return 0
+}
+
+check_pidfile_is_dead () {
+ if test ! -f lt-${1}.pid -a ! -f ${1}.pid; then
+ return 0
+ fi
+ _pid=`cat lt-${1}.pid ${1}.pid 2>/dev/null`
+ if [ -z "$_pid" ]; then
+ return 0
+ fi
+ if kill -0 $_pid 2>/dev/null; then
+ return 1
+ fi
+ return 0
+}
+
+wait_for_slave () {
+ wait_for "iprop versions to change and/or slave to catch up" get_iprop_ver "$@"
+}
+
+wait_for_slave2 () {
+ wait_for "iprop versions to change and/or second slave to catch up" get_iprop_ver2 "$@"
+}
+
+wait_for_master_down () {
+ wait_for "master to exit" check_pidfile_is_dead ipropd-master
+}
+
+wait_for_slave_down () {
+ wait_for "slave to exit" check_pidfile_is_dead ipropd-slave
+}
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f current*.log
+rm -f out-*
+rm -f mkey.file*
+rm -f messages.log messages.log
+
+> messages.log
+> messages.log2
+
+echo Creating database
+${kadmin} -l \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} -l add -p foo --use-defaults user@${R} || exit 1
+
+${kadmin} -l add --random-key --use-defaults iprop/localhost@${R} || exit 1
+${kadmin} -l ext -k ${keytab} iprop/localhost@${R} || exit 1
+${kadmin} -l add --random-key --use-defaults iprop/slave.test.h5l.se@${R} || exit 1
+${kadmin} -l ext -k ${keytab} iprop/slave.test.h5l.se@${R} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo "Test log recovery"
+${kadmin} -l add --random-key --use-defaults recovtest@${R} || exit 1
+# Test theory: save the log, make a change and save the record it
+# produced, restore the log, append to it the saved record, then add dummy
+# record.
+
+# Save the log
+cp current.log current.log.tmp
+ls -l current.log.tmp | awk '{print $5}' > tmp
+read sz < tmp
+# Make a change
+${kadmin} -l mod -a requires-pre-auth recovtest@${R} || exit 1
+${kadmin} -l get recovtest@${R} | grep 'Attributes: requires-pre-auth$' > /dev/null || exit 1
+# Save the resulting log record
+ls -l current.log | awk '{print $5}' > tmp
+read nsz < tmp
+rm tmp
+dd bs=1 if=current.log skip=$sz of=current.log.tmp.saved-record count=`expr $nsz - $sz` 2>/dev/null
+# Undo the change
+${kadmin} -l mod -a -requires-pre-auth recovtest@${R} || exit 1
+${kadmin} -l get recovtest@${R} | grep 'Attributes:.$' > /dev/null || exit 1
+# Restore the log
+cp current.log current.log.save
+mv current.log.tmp current.log
+# Append the saved record
+cat current.log.tmp.saved-record >> current.log
+rm current.log.tmp.saved-record
+# Check that we still see the principal as modified after another write forcing
+# log recovery.
+${kadmin} -l add --random-key --use-defaults dummy@${R} || exit 1
+${kadmin} -l del dummy@${R} || exit 1
+${kadmin} -l get recovtest@${R} | grep 'Attributes: requires-pre-auth$' > /dev/null || exit 1
+
+# -- foo
+ipds=
+ipdm=
+kdcpid=
+
+> iprop-stats
+> iprop-stats2
+rm -f iprop-slave-status iprop-slave-status2
+
+ipropd_slave2=$ipropd_slave
+ipropd_master2=$ipropd_master
+ipropd_slave="${ipropd_slave} --status-file=iprop-slave-status --port=$ipropport"
+ipropd_slave="${ipropd_slave} --hostname=slave.test.h5l.se -k ${keytab}"
+ipropd_slave="${ipropd_slave} --detach localhost"
+ipropd_master="${ipropd_master} --hostname=localhost -k ${keytab}"
+ipropd_master="${ipropd_master} --port=$ipropport"
+ipropd_master="${ipropd_master} --database=${objdir}/current-db --detach"
+
+ipropd_slave2="${ipropd_slave2} --status-file=iprop-slave-status2 --port=$ipropport2"
+ipropd_slave2="${ipropd_slave2} --hostname=slave.test.h5l.se -k ${keytab}"
+ipropd_slave2="${ipropd_slave2} --pidfile-basename=ipropd-slave2"
+ipropd_slave2="${ipropd_slave2} --detach localhost"
+ipropd_master2="${ipropd_master2} --hostname=localhost -k ${keytab}"
+ipropd_master2="${ipropd_master2} --port=$ipropport2"
+ipropd_master2="${ipropd_master2} --pidfile-basename=ipropd-master2"
+ipropd_master2="${ipropd_master2} --database=${objdir}/current-db.slave --detach"
+
+cleanup() {
+ echo 'killing ipropd s + m + kdc'
+ test -n "$ipdm" && kill -9 $ipdm >/dev/null 2>/dev/null
+ test -n "$ipdm2" && kill -9 $ipdm2 >/dev/null 2>/dev/null
+ test -n "$ipds" && kill -9 $ipds >/dev/null 2>/dev/null
+ test -n "$ipds2" && kill -9 $ipds2 >/dev/null 2>/dev/null
+ test -n "$kdcpid" && kill -9 $kdcpid >/dev/null 2>/dev/null
+ tail messages.log
+ tail iprop-stats
+ exit 1
+}
+trap cleanup EXIT
+
+echo Starting kdc ; > messages.log
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+echo "starting master" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} \
+${ipropd_master} || { echo "ipropd-master failed to start"; exit 1; }
+ipdm=`getpid ipropd-master`
+
+echo "starting slave" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} \
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${ipropd_slave} || { echo "ipropd-slave failed to start"; exit 1; }
+ipds=`getpid ipropd-slave`
+sh ${wait_kdc} ipropd-slave messages.log 'slave status change: up-to-date' || exit 1
+get_iprop_ver || exit 1
+
+echo "checking slave is up"
+${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Up' iprop-stats >/dev/null || exit 1
+${EGREP} 'up-to-date with version' iprop-slave-status >/dev/null || { echo "slave to up to date" ; cat iprop-slave-status ; exit 1; }
+
+# Also setup a second master on the slave, then a second slave to pull from the
+# second master.
+echo "starting master2" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} \
+KRB5_CONFIG="${objdir}/krb5-master2.conf" \
+${ipropd_master2} || { echo "second ipropd-master failed to start"; exit 1; }
+ipdm2=`getpid ipropd-master2`
+
+echo "starting slave2" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} \
+KRB5_CONFIG="${objdir}/krb5-slave2.conf" \
+${ipropd_slave2} || { echo "ipropd-slave failed to start"; exit 1; }
+ipds2=`getpid ipropd-slave2`
+sh ${wait_kdc} ipropd-slave messages2.log 'slave status change: up-to-date' || exit 1
+wait_for "Slave sees new host" get_iprop_ver2 0 || exit 1
+
+# ----------------- checking: pushing lives changes
+
+slave_get() { KRB5_CONFIG="${objdir}/krb5-slave.conf" ${kadmin} -l get "$@"; }
+slave_check_exists() {
+ # Creation with a random key is not atomic, there are at present
+ # 3 log entries to create a random key principal, the entry is
+ # "invalid" for the first two of these. We wait for the entry to
+ # exist and not be invalid
+ #
+ attrs=`slave_get -o attributes "$@" 2>/dev/null` || return 1
+ echo $attrs | egrep 'Attributes:' | egrep -v invalid >/dev/null || return 1
+ get_iprop_ver 0
+}
+
+echo "Add host"
+${kadmin} -l add --random-key --use-defaults host/foo@${R} || exit 1
+wait_for_slave
+wait_for "Slave sees new host" slave_check_exists "host/foo@${R}"
+
+echo "Rollover host keys"
+${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
+${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
+${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
+wait_for_slave 3
+slave_get host/foo@${R} | \
+ ${EGREP} Keytypes: | cut -d: -f2 | tr ' ' '
+' | sed 's/^.*[[]\(.*\)[]].*$/\1/' | grep '[0-9]' | sort -nu | tr -d '
+' | ${EGREP} 1234 > /dev/null || exit 1
+
+wait_for_slave2 4
+
+echo "Delete 3DES keys"
+${kadmin} -l del_enctype host/foo@${R} des3-cbc-sha1
+wait_for_slave
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${kadmin} -l get host/foo@${R} | \
+ ${EGREP} Keytypes: | cut -d: -f2 | tr ' ' '
+' | sed 's/^.*[[]\(.*\)[]].*$/\1/' | grep '[0-9]' | sort -nu | tr -d '
+' | ${EGREP} 1234 > /dev/null || exit 1
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${kadmin} -l get host/foo@${R} | \
+ ${EGREP} 'Keytypes:.*des3-cbc-sha1' > /dev/null && exit 1
+
+echo "Change policy host"
+${kadmin} -l modify --policy=default host/foo@${R} || exit 1
+wait_for_slave
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${kadmin} -l get host/foo@${R} > /dev/null 2>/dev/null || exit 1
+
+echo "Rename host"
+${kadmin} -l rename host/foo@${R} host/bar@${R} || exit 1
+wait_for_slave
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${kadmin} -l get host/foo@${R} > /dev/null 2>/dev/null && exit 1
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${kadmin} -l get host/bar@${R} > /dev/null || exit 1
+
+wait_for_slave2 3
+
+echo "Delete host"
+${kadmin} -l delete host/bar@${R} || exit 1
+wait_for_slave
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${kadmin} -l get host/bar@${R} > /dev/null 2>/dev/null && exit 1
+
+# See note below in LMDB sanity checking
+echo "Re-add host"
+${kadmin} -l add --random-key --use-defaults host/foo@${R} || exit 1
+${kadmin} -l add --random-key --use-defaults host/bar@${R} || exit 1
+wait_for_slave 2
+wait_for "Slave sees re-added host" slave_check_exists "host/bar@${R}"
+
+wait_for_slave2 3
+
+echo "kill slave and remove log and database"
+> iprop-stats
+sh ${leaks_kill} ipropd-slave $ipds || exit 1
+rm -f iprop-slave-status
+
+wait_for_slave_down
+${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Down' iprop-stats >/dev/null || exit 1
+
+# ----------------- checking: slave is missing changes while down
+
+rm current.slave.log current-db.slave* || exit 1
+
+echo "doing changes while slave is down"
+${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
+${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
+
+echo "Making a copy of the master log file"
+cp ${objdir}/current.log ${objdir}/current.log.tmp
+
+# ----------------- checking: checking that master and slaves resyncs
+
+echo "starting slave again" ; > messages.log
+> iprop-stats
+env ${HEIM_MALLOC_DEBUG} \
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${ipropd_slave} || { echo "ipropd-slave failed to start"; exit 1; }
+ipds=`getpid ipropd-slave`
+
+echo "checking slave is up again"
+wait_for "slave to start and connect to master" \
+ ${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Up' iprop-stats >/dev/null
+wait_for_slave 2
+wait_for_slave2 2
+${EGREP} 'up-to-date with version' iprop-slave-status >/dev/null || { echo "slave not up to date" ; cat iprop-slave-status ; exit 1; }
+echo "checking for replay problems"
+${EGREP} 'Entry already exists in database' messages.log && exit 1
+
+echo "compare versions on master and slave logs (no lock)"
+KRB5_CONFIG=${objdir}/krb5-slave.conf \
+${iprop_log} last-version -n > slave-last.tmp
+${iprop_log} last-version -n > master-last.tmp
+cmp master-last.tmp slave-last.tmp || exit 1
+
+echo "kill slave and remove log and database"
+sh ${leaks_kill} ipropd-slave $ipds || exit 1
+wait_for_slave_down
+
+rm current.slave.log current-db.slave* || exit 1
+> iprop-stats
+rm -f iprop-slave-status
+echo "starting slave" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} \
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${ipropd_slave} || { echo "ipropd-slave failed to start"; exit 1; }
+ipds=`getpid ipropd-slave`
+wait_for_slave 0
+
+echo "checking slave is up again"
+wait_for "slave to start and connect to master" \
+ ${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Up' iprop-stats >/dev/null
+${EGREP} 'up-to-date with version' iprop-slave-status >/dev/null || { echo "slave not up to date" ; cat iprop-slave-status ; exit 1; }
+echo "checking for replay problems"
+${EGREP} 'Entry already exists in database' messages.log && exit 1
+
+# ----------------- checking: checking live truncation of master log
+
+${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
+wait_for_slave
+wait_for_slave2
+
+echo "live truncate on master log"
+${iprop_log} truncate -K 5 || exit 1
+wait_for_slave 0
+
+echo "Killing master and slave"
+sh ${leaks_kill} ipropd-master $ipdm || exit 1
+sh ${leaks_kill} ipropd-slave $ipds || exit 1
+
+rm -f iprop-slave-status
+
+wait_for_slave_down
+wait_for_master_down
+
+echo "compare versions on master and slave logs"
+KRB5_CONFIG=${objdir}/krb5-slave.conf \
+${iprop_log} last-version > slave-last.tmp
+${iprop_log} last-version > master-last.tmp
+cmp master-last.tmp slave-last.tmp || exit 1
+
+# ----------------- checking: master going backward
+> iprop-stats
+> messages.log
+
+echo "Going back to old version of the master log file"
+cp ${objdir}/current.log.tmp ${objdir}/current.log
+
+echo "starting master" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} \
+${ipropd_master} || { echo "ipropd-master failed to start"; exit 1; }
+ipdm=`getpid ipropd-master`
+
+echo "starting slave" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} \
+KRB5_CONFIG="${objdir}/krb5-slave.conf" \
+${ipropd_slave} || { echo "ipropd-slave failed to start"; exit 1; }
+ipds=`getpid ipropd-slave`
+wait_for_slave -1
+
+echo "checking slave is up again"
+wait_for "slave to start and connect to master" \
+ ${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Up' iprop-stats >/dev/null
+${EGREP} 'up-to-date with version' iprop-slave-status >/dev/null || { echo "slave to up to date" ; cat iprop-slave-status ; exit 1; }
+echo "checking for replay problems"
+${EGREP} 'Entry already exists in database' messages.log && exit 1
+
+echo "pushing one change"
+${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
+wait_for_slave
+wait_for_slave2 0
+
+echo "Killing master"
+sh ${leaks_kill} ipropd-master $ipdm || exit 1
+
+wait_for_master_down
+
+wait_for "slave to disconnect" \
+ ${EGREP} 'disconnected' iprop-slave-status >/dev/null
+
+if ! tail -30 messages.log | grep 'disconnected for server' > /dev/null; then
+ echo "client didnt disconnect"
+ exit 1
+fi
+
+echo "probing for slave pid"
+kill -0 ${ipds} || { echo "slave no longer there"; exit 1; }
+
+> messages.log
+
+echo "Staring master again" ; > messages.log
+env ${HEIM_MALLOC_DEBUG} \
+${ipropd_master} || { echo "ipropd-master failed to start"; exit 1; }
+ipdm=`getpid ipropd-master`
+
+echo "probing for slave pid"
+kill -0 ${ipds} || { echo "slave no longer there"; exit 1; }
+
+
+echo "pushing one change"
+${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
+wait_for_slave
+wait_for_slave2
+
+echo "shutting down all services"
+
+leaked=false
+sh ${leaks_kill} kdc $kdcpid || leaked=true
+sh ${leaks_kill} ipropd-master $ipdm || leaked=true
+sh ${leaks_kill} ipropd-slave $ipds || leaked=true
+sh ${leaks_kill} ipropd-master $ipdm2 || leaked=true
+sh ${leaks_kill} ipropd-slave $ipds2 || leaked=true
+rm -f iprop-slave-status
+trap "" EXIT
+$leaked && exit 1
+
+echo "compare versions on master and slave logs"
+KRB5_CONFIG=${objdir}/krb5-slave.conf \
+${iprop_log} last-version > slave-last.tmp
+${iprop_log} last-version > master-last.tmp
+cmp master-last.tmp slave-last.tmp || exit 1
+
+if [ "$db_type" = lmdb ] && type mdb_stat > /dev/null 2>&1; then
+ # Sanity check that we have the same number of principals at the HDB
+ # and LMDB levels.
+ #
+ # We should also do this for the sqlite backend, but that would
+ # require a sqlite3(1) shell that is capable of opening our HDB
+ # files.
+ echo "checking that principals in DB == entries in LMDB"
+ # Add one to match lmdb overhead
+ princs=`(echo; ${kadmin} -l list '*') | wc -l`
+ entries=`mdb_stat -n current-db.mdb | grep 'Entries:' | awk '{print $2}'`
+ [ "$princs" -eq "$entries" ] || exit 1
+fi
+
+exit 0
diff --git a/third_party/heimdal/tests/kdc/check-kadmin.in b/third_party/heimdal/tests/kdc/check-kadmin.in
new file mode 100644
index 0000000..339868b
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-kadmin.in
@@ -0,0 +1,456 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+srcdir="@srcdir@"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+R2=TEST2.H5L.SE
+
+port=@port@
+admport=@admport@
+
+cache="FILE:${objdir}/cache.krb5"
+
+kadmin="${kadmin} -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+kadmind="${kadmind} -p $admport"
+
+server=host/datan.test.h5l.se
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+
+foopassword="fooLongPasswordYo123;"
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+rm -f messages.log
+
+> messages.log
+
+echo Creating database
+${kadmin} -l \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} -l add -p "$foopassword" --use-defaults foo/admin@${R} || exit 1
+${kadmin} -l add -p "$foopassword" --use-defaults bar@${R} || exit 1
+${kadmin} -l add -p "$foopassword" --use-defaults baz@${R} || exit 1
+${kadmin} -l add -p "$foopassword" --use-defaults bez@${R} || exit 1
+${kadmin} -l add -p "$foopassword" --use-defaults fez@${R} || exit 1
+${kadmin} -l add -p "$foopassword" --use-defaults hasalias@${R} || exit 1
+${kadmin} -l add -p "$foopassword" --use-defaults pkinit@${R} || exit 1
+${kadmin} -l modify --pkinit-acl="CN=baz,DC=test,DC=h5l,DC=se" pkinit@${R} || exit 1
+${kadmin} -l add -p "$foopassword" --use-defaults prune@${R} || exit 1
+${kadmin} -l cpw --keepold --random-key prune@${R} || exit 1
+${kadmin} -l cpw --keepold --random-key prune@${R} || exit 1
+${kadmin} -l add -p "$foopassword" --use-defaults pruneall@${R} || exit 1
+${kadmin} -l cpw --pruneall --random-key pruneall@${R} || exit 1
+${kadmin} -l cpw --pruneall --random-key pruneall@${R} || exit 1
+
+echo "$foopassword" > ${objdir}/foopassword
+
+echo Starting kdc ; > messages.log
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+echo Starting kadmind
+${kadmind} --detach --list-chunk-size=1 \
+ || { echo "kadmind failed to start"; cat messages.log; exit 1; }
+kadmpid=`getpid kadmind`
+
+trap "kill -9 ${kdcpid} ${kadmpid}" EXIT
+
+#----------------------------------
+echo "kinit (no admin); test mod --alias authorization"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} hasalias@${R} || exit 1
+
+# Check that one non-permitted alias -> failure
+env KRB5CCNAME=${cache} \
+${kadmin} -p hasalias@${R} modify --alias=goodalias1@${R} --alias=badalias@${R} hasalias@${R} &&
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+# Check that all permitted aliases -> success
+env KRB5CCNAME=${cache} \
+${kadmin} -p hasalias@${R} modify --alias=goodalias1@${R} --alias=goodalias2@${R} hasalias@${R} ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+# Check that we can drop aliases
+env KRB5CCNAME=${cache} \
+${kadmin} -p hasalias@${R} modify --alias=goodalias3@${R} hasalias@${R} ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+${kadmin} -l get hasalias@${R} | grep Aliases: > kadmin.tmp
+read junk aliases < kadmin.tmp
+rm kadmin.tmp
+[ "$aliases" != "goodalias3@${R}" ] && { echo "kadmind failed $?"; cat messages.log ; exit 1; }
+
+env KRB5CCNAME=${cache} \
+${kadmin} -p hasalias@${R} modify --alias=goodalias1@${R} --alias=goodalias2@${R} --alias=goodalias3@${R} hasalias@${R} ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+${kadmin} -l get hasalias@${R} | grep Aliases: > kadmin.tmp
+read junk aliases < kadmin.tmp
+rm kadmin.tmp
+[ "$aliases" != "goodalias1@${R} goodalias2@${R} goodalias3@${R}" ] && { echo "FOO failed $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kinit (no admin)"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} bar@${R} || exit 1
+echo "kadmin"
+env KRB5CCNAME=${cache} \
+${kadmin} -p bar@${R} add -p "$foopassword" --use-defaults kaka2@${R} ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+${kadmin} -l get kaka2@${R} > /dev/null ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kinit (no admin)"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} baz@${R} || exit 1
+echo "kadmin globacl"
+env KRB5CCNAME=${cache} \
+${kadmin} -p baz@${R} get bar@${R} > /dev/null ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kinit (no admin)"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} baz@${R} || exit 1
+echo "kadmin globacl, negative"
+env KRB5CCNAME=${cache} \
+${kadmin} -p baz@${R} passwd -p "$foopassword" bar@${R} > /dev/null 2>/dev/null &&
+ { echo "kadmin succesded $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kinit (no admin)"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} baz@${R} || exit 1
+echo "kadmin globacl"
+env KRB5CCNAME=${cache} \
+${kadmin} -p baz@${R} get bar@${R} > /dev/null ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kinit (no admin)"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} bez@${R} || exit 1
+echo "kadmin globacl, negative"
+env KRB5CCNAME=${cache} \
+${kadmin} -p bez@${R} passwd -p "$foopassword" bar@${R} > /dev/null 2>/dev/null &&
+ { echo "kadmin succesded $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kinit (no admin)"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} fez@${R} || exit 1
+echo "kadmin globacl"
+env KRB5CCNAME=${cache} \
+${kadmin} -p fez@${R} get bar@${R} > /dev/null ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kinit (no admin)"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} fez@${R} || exit 1
+echo "kadmin globacl, negative"
+env KRB5CCNAME=${cache} \
+${kadmin} -p fez@${R} passwd -p "$foopassword" bar@${R} > /dev/null 2>/dev/null &&
+ { echo "kadmin succesded $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kinit (admin)"
+${kinit} --password-file=${objdir}/foopassword \
+ -S kadmin/admin@${R} foo/admin@${R} || exit 1
+
+echo "kadmin"
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} add -p "$foopassword" --use-defaults kaka@${R} ||
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+echo "kadmin"
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} add -p abc --use-defaults kaka@${R} &&
+ { echo "kadmin succeeded $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kadmin get doesnotexists"
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} get -s doesnotexists@${R} \
+ > /dev/null 2>kadmin.tmp && \
+ { echo "kadmin passed"; cat messages.log ; exit 1; }
+
+# evil hack to support libtool
+sed 's/lt-kadmin:/kadmin:/' < kadmin.tmp > kadmin2.tmp
+mv kadmin2.tmp kadmin.tmp
+
+# If client tried IPv6, but service only listened on IPv4
+grep -v ': connect' kadmin.tmp > kadmin2.tmp
+mv kadmin2.tmp kadmin.tmp
+
+diff kadmin.tmp ${srcdir}/donotexists.txt || \
+ { echo "wrong response"; exit 1;}
+
+#----------------------------------
+echo "kadmin get pkinit-acl"
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} get -o pkinit-acl pkinit@${R} \
+ > /dev/null || \
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kadmin get -o principal"
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} get -o principal bar@${R} \
+ > kadmin.tmp 2>&1 || \
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+if test "`cat kadmin.tmp`" != "Principal: bar@TEST.H5L.SE" ; then
+ cat kadmin.tmp ; cat messages.log ; exit 1 ;
+fi
+
+
+#----------------------------------
+echo "kadmin get -o kvno"
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} get -o kvno bar@${R} \
+ > kadmin.tmp 2>&1 || \
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+if test "`cat kadmin.tmp`" != "Kvno: 1" ; then
+ cat kadmin.tmp ; cat messages.log ; exit 1 ;
+fi
+
+
+#----------------------------------
+echo "kadmin get -o princ_expire_time"
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} get -o princ_expire_time bar@${R} \
+ > kadmin.tmp 2>&1 || \
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+if test "`cat kadmin.tmp`" != "Principal expires: never" ; then
+ cat kadmin.tmp ; cat messages.log ; exit 1 ;
+fi
+
+#----------------------------------
+echo "kadmin get -s -o attributes"
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} get -s -o attributes bar@${R} \
+ > kadmin.tmp || \
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+if test "`cat kadmin.tmp`" != "Attributes" ; then
+ cat kadmin.tmp ; cat messages.log ; exit 1 ;
+fi
+
+#----------------------------------
+echo "kadmin prune"
+env KRB5CCNAME=${cache} \
+${kadmin} prune --kvno=2 prune@${R} \
+ > kadmin.tmp 2>&1 || \
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+env KRB5CCNAME=${cache} \
+${kadmin} get prune@${R} \
+ > kadmin.tmp 2>&1 || \
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+cat kadmin.tmp | ${EGREP} Keytypes: | cut -d: -f2 | tr ' ' '
+' | sed 's/^.*[[]\(.*\)[]].*$/\1/' | grep '[0-9]' | sort -nu | tr -d '
+' | ${EGREP} '^13$' > /dev/null || \
+ { echo "kadmin prune failed $?"; cat messages.log ; exit 1; }
+
+#----------------------------------
+echo "kadmin pruneall"
+env KRB5CCNAME=${cache} \
+${kadmin} get pruneall@${R} \
+ > kadmin.tmp 2>&1 || \
+ { echo "kadmin failed $?"; cat messages.log ; exit 1; }
+cat kadmin.tmp | ${EGREP} Keytypes: | cut -d: -f2 | tr ' ' '
+' | sed 's/^.*[[]\(.*\)[]].*$/\1/' | grep '[0-9]' | sort -nu | tr -d '
+' | ${EGREP} '^3$' > /dev/null || \
+ { echo "kadmin pruneall failed $?"; cat messages.log ; exit 1; }
+
+env KRB5CCNAME=${cache} \
+ ${kadmin} -p foo/admin@${R} list --upto=3 '*' > kadmin.tmp
+[ `wc -l < kadmin.tmp` -eq 3 ] ||
+ { echo "kadmin list --upto 3 produced `wc -l < kadmin.tmp` results!"; exit 1; }
+
+#----------------------------------
+echo "kadmin get '*' (re-entrance)"; > messages.log
+${kadmin} -l get '*' > kadmin.tmp ||
+ { echo "failed to list principals"; cat messages.log ; exit 1; }
+> messages.log
+env KRB5CCNAME=${cache} \
+ ${kadmin} -p foo/admin@${R} get '*' > kadmin.tmp2 ||
+ { echo "failed to list principals"; cat messages.log ; exit 1; }
+diff -u kadmin.tmp kadmin.tmp2 ||
+ { echo "local and remote get all differ"; exit 1; }
+
+#----------------------------------
+# We have 20 principals in the DB. Test two chunks of 1 (since that's how we
+# started kadmind above.
+> messages.log
+echo "kadmin list all (chunk size 1)"
+# Check that list produces the same output locally and remote.
+env KRB5CCNAME=${cache} \
+ ${kadmin} -p foo/admin@${R} list '*' | sort > kadmin.tmp ||
+ { echo "failed to list principals"; cat messages.log ; exit 1; }
+${kadmin} -l list '*' | sort > kadmin.tmp2
+diff kadmin.tmp kadmin.tmp2 ||
+ { echo "failed to list all principals"; cat messages.log ; exit 1; }
+# kadmin dump does not use kadm5_iter_principals, so this is a good way to
+# double check the above results. This time we drop the realm part because
+# kadmin doesn't show us the realm for principals in the default realm.
+${kadmin} -l list '*' | cut -d'@' -f1 | sort > kadmin.tmp
+${kadmin} -l dump | cut -d'@' -f1 | sort > kadmin.tmp2
+diff kadmin.tmp kadmin.tmp2 ||
+ { echo "failed to list all principals (dump)"; cat messages.log ; exit 1; }
+${kadmin} -l > kadmin.tmp <<"EOF"
+list *
+get foo/admin
+EOF
+grep Attributes kadmin.tmp > /dev/null ||
+ { echo "failed to execute command after list"; cat messages.log ; exit 1; }
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} > kadmin.tmp <<"EOF"
+list *
+get foo/admin
+EOF
+grep Attributes kadmin.tmp > /dev/null ||
+ { echo "failed to execute command after list"; cat messages.log ; exit 1; }
+
+#----------------------------------
+# We have 20 principals in the DB. Test two chunks of 10.
+sh ${leaks_kill} kadmind $kadmpid || exit 1
+${kadmind} --list-chunk-size=10 --detach
+kadmpid=`getpid kadmind`
+
+> messages.log
+echo "kadmin list all (chunk size 10)"
+# Check that list produces the same output locally and remote.
+env KRB5CCNAME=${cache} \
+ ${kadmin} -p foo/admin@${R} list '*' | sort > kadmin.tmp ||
+ { echo "failed to list principals"; cat messages.log ; exit 1; }
+${kadmin} -l list '*' | sort > kadmin.tmp2
+diff kadmin.tmp kadmin.tmp2 ||
+ { echo "failed to list all principals"; cat messages.log ; exit 1; }
+# kadmin dump does not use kadm5_iter_principals, so this is a good way to
+# double check the above results. This time we drop the realm part because
+# kadmin doesn't show us the realm for principals in the default realm.
+${kadmin} -l list '*' | cut -d'@' -f1 | sort > kadmin.tmp
+${kadmin} -l dump | cut -d'@' -f1 | sort > kadmin.tmp2
+diff kadmin.tmp kadmin.tmp2 ||
+ { echo "failed to list all principals (dump)"; cat messages.log ; exit 1; }
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} > kadmin.tmp <<"EOF"
+list *
+get foo/admin
+EOF
+grep Attributes kadmin.tmp > /dev/null ||
+ { echo "failed to execute command after list"; cat messages.log ; exit 1; }
+
+#----------------------------------
+# We have 20 principals in the DB. Test one chunk of 50.
+sh ${leaks_kill} kadmind $kadmpid || exit 1
+${kadmind} --list-chunk-size=50 --detach
+kadmpid=`getpid kadmind`
+
+> messages.log
+echo "kadmin list all (chunk size 50)"
+# Check that list produces the same output locally and remote.
+env KRB5CCNAME=${cache} \
+ ${kadmin} -p foo/admin@${R} list '*' | sort > kadmin.tmp ||
+ { echo "failed to list principals"; cat messages.log ; exit 1; }
+${kadmin} -l list '*' | sort > kadmin.tmp2
+diff kadmin.tmp kadmin.tmp2 ||
+ { echo "failed to list all principals"; cat messages.log ; exit 1; }
+# kadmin dump does not use kadm5_iter_principals, so this is a good way to
+# double check the above results. This time we drop the realm part because
+# kadmin doesn't show us the realm for principals in the default realm.
+${kadmin} -l list '*' | cut -d'@' -f1 | sort > kadmin.tmp
+${kadmin} -l dump | cut -d'@' -f1 | sort > kadmin.tmp2
+diff kadmin.tmp kadmin.tmp2 ||
+ { echo "failed to list all principals (dump)"; cat messages.log ; exit 1; }
+env KRB5CCNAME=${cache} \
+${kadmin} -p foo/admin@${R} > kadmin.tmp <<"EOF"
+list *
+get foo/admin
+EOF
+grep Attributes kadmin.tmp > /dev/null ||
+ { echo "failed to execute command after list"; cat messages.log ; exit 1; }
+
+#----------------------------------
+# We have 20 principals in the DB. Test 3 chunks of up to 7.
+sh ${leaks_kill} kadmind $kadmpid || exit 1
+${kadmind} --list-chunk-size=7 --detach
+kadmpid=`getpid kadmind`
+
+> messages.log
+echo "kadmin list all (chunk size 7)"
+# Check that list produces the same output locally and remote.
+env KRB5CCNAME=${cache} \
+ ${kadmin} -p foo/admin@${R} list '*' | sort > kadmin.tmp ||
+ { echo "failed to list principals"; cat messages.log ; exit 1; }
+${kadmin} -l list '*' | sort > kadmin.tmp2
+diff kadmin.tmp kadmin.tmp2 ||
+ { echo "failed to list all principals"; cat messages.log ; exit 1; }
+# kadmin dump does not use kadm5_iter_principals, so this is a good way to
+# double check the above results. This time we drop the realm part because
+# kadmin doesn't show us the realm for principals in the default realm.
+${kadmin} -l list '*' | cut -d'@' -f1 | sort > kadmin.tmp
+${kadmin} -l dump | cut -d'@' -f1 | sort > kadmin.tmp2
+diff kadmin.tmp kadmin.tmp2 ||
+ { echo "failed to list all principals (dump)"; cat messages.log ; exit 1; }
+
+#----------------------------------
+
+echo "killing kdc (${kdcpid} ${kadmpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+sh ${leaks_kill} kadmind $kadmpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-kdc-weak.in b/third_party/heimdal/tests/kdc/check-kdc-weak.in
new file mode 100644
index 0000000..182f530
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-kdc-weak.in
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+objdir="@objdir@"
+
+exec ${top_builddir}/tests/kdc/check-kdc ${objdir}/krb5-weak.conf
diff --git a/third_party/heimdal/tests/kdc/check-kdc.in b/third_party/heimdal/tests/kdc/check-kdc.in
new file mode 100644
index 0000000..307312e
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-kdc.in
@@ -0,0 +1,1131 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+KRB5_CONFIG="${1-${objdir}/krb5.conf}"
+export KRB5_CONFIG
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+RH=TEST-HTTP.H5L.SE
+R2=TEST2.H5L.SE
+R3=TEST3.H5L.SE
+R4=TEST4.H5L.SE
+R5=SOME-REALM5.FR
+R6=SOME-REALM6.US
+R7=SOME-REALM7.UK
+R8=SOME-REALM8.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@
+
+kadmin5="${kadmin} -l -r $R5"
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+kpasswdd="${kpasswdd} --addresses=localhost -p $pwport"
+
+server=host/datan.test.h5l.se
+server2=host/computer.example.com
+server3=host/refer-me-out.test.h5l.se
+server4=host/no-auth-data-reqd.test.h5l.se
+server5=host/a-host.refer-all-out.test.h5l.se
+namespace=WELLKNOWN/HOSTBASED-NAMESPACE/_/refer-all-out.test.h5l.se
+serverip=host/10.11.12.13
+serveripname=host/ip.test.h5l.org
+serveripname2=host/10.11.12.14
+alias1=host/datan.example.com
+alias2=host/datan
+aliaskeytab=host/datan
+cache="FILE:${objdir}/cache.krb5"
+ocache="FILE:${objdir}/ocache.krb5"
+o2cache="FILE:${objdir}/o2cache.krb5"
+icache="FILE:${objdir}/icache.krb5"
+keytabfile=${objdir}/server.keytab
+keytab="FILE:${keytabfile}"
+ps="proxy-service@${R}"
+rps="restricted-proxy-service@${R}"
+aesenctype="aes256-cts-hmac-sha1-96"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist2="${klist} -c $o2cache"
+klist="${klist} -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kgetcred_imp="${kgetcred} -c $cache --out-cache=${ocache}"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+kimpersonate="${kimpersonate} -k ${keytab} --ccache=${ocache}"
+test_set_kvno0="${test_set_kvno0} -c $cache"
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R2} || exit 1
+
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R3} || exit 1
+
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R4} || exit 1
+
+${kadmin5} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R5} || exit 1
+
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R6} || exit 1
+
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R7} || exit 1
+
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R8} || 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 \
+ --realm-max-renewable-life=1month \
+ ${RH} || exit 1
+
+${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
+${kadmin} cpw -r krbtgt/${R}@${R} || exit 1
+${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@${R8} || 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
+${kadmin} cpw -p bla --keepold ${server}@${R} || exit 1
+${kadmin} cpw -p kaka --keepold ${server}@${R} || exit 1
+${kadmin} add -p kaka --use-defaults ${server}-des3@${R} || exit 1
+${kadmin} add -p kaka --use-defaults kt-des3@${R} || exit 1
+${kadmin} add -p kaka --use-defaults foo/des3-only@${R} || exit 1
+${kadmin} add -p kaka --use-defaults bar/des3-only@${R} || exit 1
+${kadmin} add -p kaka --use-defaults foo/aes-only@${R} || exit 1
+
+${kadmin} add -p sens --use-defaults --attributes=disallow-forwardable sensitive@${R} || exit 1
+${kadmin} add -p foo --use-defaults ${ps} || exit 1
+${kadmin} modify --attributes=+trusted-for-delegation ${ps} || exit 1
+${kadmin} modify --constrained-delegation=${server} ${ps} || exit 1
+${kadmin} ext -k ${keytab} ${server}@${R} || exit 1
+${kadmin} ext -k ${keytab} ${ps} || exit 1
+
+# Note: rps is not trusted-for-delegation
+${kadmin} add -p foo --use-defaults ${rps} || exit 1
+${kadmin} modify --constrained-delegation=${server} ${rps} || exit 1
+${kadmin} ext -k ${keytab} ${rps} || exit 1
+
+${kadmin} add -p kaka --use-defaults ${server2}@${R2} || exit 1
+${kadmin} ext -k ${keytab} ${server2}@${R2} || exit 1
+${kadmin} add -p foo --use-defaults WELLKNOWN/REFERRALS/TARGET@${R5} || exit 1
+${kadmin} add_alias WELLKNOWN/REFERRALS/TARGET@${R5} ${server3}@${R} || exit 1
+${kadmin5} add -p kaka --use-defaults ${server3}@${R5} || exit 1
+${kadmin5} ext -k ${keytab} ${server3}@${R5} || exit 1
+${kadmin} add_alias WELLKNOWN/REFERRALS/TARGET@${R5} ${namespace}@${R} || exit 1
+${kadmin5} add -p kaka --use-defaults ${server5}@${R5} || exit 1
+${kadmin5} ext -k ${keytab} ${server5}@${R5} || exit 1
+${kadmin} add -p kaka --use-defaults ${serverip}@${R} || exit 1
+${kadmin} ext -k ${keytab} ${serverip}@${R} || exit 1
+${kadmin} add -p kaka --use-defaults ${serveripname}@${R} || exit 1
+${kadmin} ext -k ${keytab} ${serveripname}@${R} || exit 1
+${kadmin} modify --alias=${serveripname2}@${R} ${serveripname}@${R}
+${kadmin} add -p foo --use-defaults remove2@${R2} || exit 1
+
+${kadmin} add -p nopac --use-defaults ${server4}@${R2} || exit 1
+${kadmin} modify --attributes=+no-auth-data-reqd ${server4}@${R2} || exit 1
+${kadmin} ext -k ${keytab} ${server4}@${R2} || exit 1
+
+${kadmin} add -p kaka --use-defaults ${alias1}@${R} || exit 1
+${kadmin} ext -k ${keytab} ${alias1}@${R} || exit 1
+${kadmin} modify --alias=${alias2}@${R} ${alias1}@${R}
+
+${kadmin} add -p cross1 --use-defaults krbtgt/${R2}@${R} || exit 1
+${kadmin} modify --attributes=+no-auth-data-reqd krbtgt/${R2}@${R} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R}@${R2} || exit 1
+
+${kadmin} add -p cross1 --use-defaults krbtgt/${R3}@${R2} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R2}@${R3} || exit 1
+
+${kadmin} add -p cross1 --use-defaults krbtgt/${R4}@${R2} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R2}@${R4} || exit 1
+
+${kadmin} add -p cross1 --use-defaults krbtgt/${R4}@${R3} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R3}@${R4} || exit 1
+
+${kadmin} add -p cross1 --use-defaults krbtgt/${R5}@${R} || exit 1
+${kadmin5} add -p cross2 --use-defaults krbtgt/${R}@${R5} || exit 1
+
+${kadmin5} add -p cross1 --use-defaults krbtgt/${R6}@${R5} || exit 1
+${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/${R8}@${R6} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R6}@${R8} || 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
+
+${kadmin} add -p foo --use-defaults pw-expired@${R} || exit 1
+${kadmin} modify --pw-expiration-time=2012-06-12 pw-expired@${R} || exit 1
+
+${kadmin} add -p foo --use-defaults account-expired@${R} || exit 1
+${kadmin} modify --expiration-time=2012-06-12 account-expired@${R} || exit 1
+
+${kadmin} add -p foo --use-defaults foo@${RH} || exit 1
+
+echo "Check parser"
+${kadmin} add -p foo --use-defaults -- -p || exit 1
+${kadmin} delete -- -p || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+${kadmin} check ${R2} || exit 1
+${kadmin} check ${R3} || exit 1
+${kadmin} check ${R4} || exit 1
+${kadmin5} check ${R5} || exit 1
+${kadmin} check ${R6} || exit 1
+${kadmin} check ${R7} || exit 1
+${kadmin} check ${R8} || 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
+${EGREP} -v '^FILE:' tempfile | ${EGREP} -v '^Vno' | ${EGREP} -v '^$' | \
+ ${EGREP} -v "$server" | # we did cpw for this one
+ awk '$1 !~ /1/ { exit 1 }' || exit 1
+${EGREP} -v '^FILE:' tempfile | ${EGREP} -v '^Vno' | ${EGREP} -v '^$' | \
+ ${EGREP} "$server" | head -1 |
+ awk '$1 !~ /3/ { exit 1 }' || exit 1
+
+
+${kadmin} get foo@${R} > tempfile || exit 1
+enctypes=`grep Keytypes: tempfile | sed 's/(pw-salt)//g' | sed 's/,//g' | sed 's/Keytypes://' | sed 's/\[[0-9]*\]//g'`
+
+enctype_sans_aes=`echo $enctypes | sed 's/aes[^ ]*//g'`
+enctype_sans_des3=`echo $enctypes | sed 's/des3-cbc-sha1//g'`
+
+echo "deleting all but des enctypes on kt-des3 in keytab"
+${kadmin} ext -k ${keytab} kt-des3@${R} || exit 1
+for a in ${enctype_sans_des3} ; do
+ ${ktutil} -k ${keytab} remove -p kt-des3@${R} -e $a
+done
+
+echo "checking globbing keys rules"
+${kadmin} get foo/des3-only@${R} > tempfile || exit 1
+enctypes=`grep Keytypes: tempfile | sed 's/(pw-salt)//g' | sed 's/,//g' | sed 's/Keytypes://' | sed 's/\[[0-9]*\]//g' | sed 's/ //g'`
+if [ X"$enctypes" != Xdes3-cbc-sha1 ] ; then
+ echo "des3 only is not only des3: $enctypes"
+ exit 1
+fi
+
+${kadmin} get foo/aes-only@${R} > tempfile || exit 1
+enctypes=`grep Keytypes: tempfile | sed 's/(pw-salt)//g' | sed 's/,//g' | sed 's/Keytypes://' | sed 's/\[[0-9]*\]//g' | sed 's/ //g'`
+if [ X"$enctypes" != Xaes256-cts-hmac-sha1-96 ] ; then
+ echo "aes only is not only aes: $enctypes"
+ exit 1
+fi
+
+
+echo foo > ${objdir}/foopassword
+echo notfoo > ${objdir}/notfoopassword
+
+echo Starting kdc ; > messages.log
+env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
+${kdc} --detach --testing ||
+ { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+echo Starting kpasswdd; > messages.log
+env ${HEIM_MALLOC_DEBUG} ${kpasswdd} --detach ||
+ { echo "kpasswdd failed to start"; exit 1; }
+kpasswddpid=`getpid kpasswdd`
+
+
+trap "kill -9 ${kdcpid} ${kpasswddpid}; echo signal killing kdc kpasswdd; exit 1;" EXIT
+
+ec=0
+
+echo "Getting client initial tickets with wrong password"; > messages.log
+${kadmin} modify --attributes=+disallow-client ${server} || exit 1
+${kinit} --password-file=${objdir}/notfoopassword \
+ foo@${R} 2>kinit-log.tmp && \
+ { ec=1 ; eval "${testfailed}"; }
+grep 'Password incorrect' kinit-log.tmp > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Doing krbtgt key rollover"; > messages.log
+${kadmin} cpw -r --keepold krbtgt/${R}@${R} || exit 1
+echo "Getting tickets"; > messages.log
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Listing tickets"; > messages.log
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client initial tickets (http transport)"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@${RH} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Testing capaths logic"
+${kinit} --password-file=${objdir}/foopassword \
+ -e ${aesenctype} -e ${aesenctype} \
+ foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Getting x-realm tickets with capaths for $R -> $R2"
+${kgetcred} foo@${R2} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R3"
+${kgetcred} foo@${R3} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R4"
+${kgetcred} foo@${R4} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R5"
+${kgetcred} foo@${R5} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R6"
+${kgetcred} foo@${R6} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R7"
+${kgetcred} foo@${R7} || { ec=1 ; eval "${testfailed}"; }
+echo "Should not get x-realm tickets with capaths for $R -> $R8"
+${kgetcred} foo@${R8} && { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Testing capaths logic (reverse order)"
+${kinit} --password-file=${objdir}/foopassword \
+ -e ${aesenctype} -e ${aesenctype} \
+ foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Getting x-realm tickets with capaths for $R -> $R4"
+${kgetcred} foo@${R4} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R3"
+${kgetcred} foo@${R3} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R2"
+${kgetcred} foo@${R2} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R7"
+${kgetcred} foo@${R7} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R6"
+${kgetcred} foo@${R6} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting x-realm tickets with capaths for $R -> $R5"
+${kgetcred} foo@${R5} || { ec=1 ; eval "${testfailed}"; }
+echo "Testing HDB referral entry"
+${kgetcred} --canonicalize ${server3}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Testing HDB namespace referral entry"
+${kgetcred} --canonicalize ${server5}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist}
+${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 HDB referral alias for $R1 -> $R3"
+${kgetcred} --hostbased --canonicalize foo host.${h1} || { 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}"; }
+fgrep "cross-realm ${H3} -> ${H1} via [${H2}, ${R}]" messages.log > /dev/null || { 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}"; }
+fgrep "cross-realm ${H3} -> ${R} via [${H2}]" messages.log > /dev/null || { 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}"; }
+fgrep "cross-realm ${H3} -> ${H2}" messages.log > /dev/null || { 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}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} -f | grep ${server} | grep FRA > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Testing strip of forwardable when the server is disallowed in TGS-REQ"
+${kgetcred} sensitive@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} -f | grep sensitive | grep FRA > /dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Specific enctype"; > messages.log
+${kinit} --password-file=${objdir}/foopassword \
+ -e ${aesenctype} -e ${aesenctype} \
+ foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+
+for a in $enctypes; do
+ echo "Getting client initial tickets ($a)"; > messages.log
+ ${kinit} --enctype=$a --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
+ echo "Getting tickets"; > messages.log
+ ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} ${server}@${R} ${keytab} ${cache} || { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy}
+done
+
+
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+for a in $enctypes; do
+ echo "Getting tickets ($a)"; > messages.log
+ ${kgetcred} -e $a ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server}@${R}
+done
+${kdestroy}
+
+echo "Getting client initial tickets without PAC"; > messages.log
+${kinit} --no-request-pac --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+for a in $enctypes; do
+ echo "Getting tickets ($a)"; > messages.log
+ ${kgetcred} -e $a ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} ${server}@${R} ${keytab} ${cache} && \
+ { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} --no-verify-pac ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server}@${R}
+done
+${kdestroy}
+
+echo "Getting client initial tickets with PAC"; > messages.log
+${kinit} --request-pac --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+for a in $enctypes; do
+ echo "Getting tickets for PAC-less service principal ($a)"; > messages.log
+ ${kgetcred} -e $a ${server4}@${R2} || { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} --verify-pac ${server4}@${R2} ${keytab} ${cache} && \
+ { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} --no-verify-pac ${server4}@${R2} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server4}@${R2}
+done
+${kdestroy}
+
+echo "Getting client initial tickets with PAC"; > messages.log
+${kinit} --request-pac --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+for a in $enctypes; do
+ echo "Getting tickets for PAC-less service principal ($a)"; > messages.log
+ ${kgetcred} -e $a ${server4}@${R2} || { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} --verify-pac ${server4}@${R2} ${keytab} ${cache} && \
+ { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} --no-verify-pac ${server4}@${R2} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server4}@${R2}
+done
+${kdestroy}
+
+echo "Getting client authenticated anonymous initial tickets"; > messages.log
+${kinit} -n --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+for a in $enctypes; do
+ echo "Getting tickets ($a)"; > messages.log
+ ${kgetcred} -e $a ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} --no-verify-pac ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} --verify-pac ${server}@${R} ${keytab} ${cache} && \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server}@${R}
+done
+${kdestroy}
+
+echo "Getting client anonymous service tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+for a in $enctypes; do
+ echo "Getting tickets ($a)"; > messages.log
+ ${kgetcred} -n -e $a ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server}@${R}
+done
+${kdestroy}
+
+echo "Getting client initial tickets for cross realm case (no-auth-data-reqd for ${R2})"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
+for a in $enctypes; do
+ echo "Getting cross realm tickets ($a)"; > messages.log
+ ${kgetcred} -e $a ${server2}@${R2} || { ec=1 ; eval "${testfailed}"; }
+ echo " checking we we got back right ticket"
+ ${klist} | grep ${server2}@ > /dev/null || { ec=1 ; eval "${testfailed}"; }
+ echo " checking if ticket is useful"
+ ${test_ap_req} --no-verify-pac ${server2}@${R2} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} --verify-pac ${server2}@${R2} ${keytab} ${cache} && \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server2}@${R2}
+done
+${kdestroy}
+
+echo "Getting client initial tickets for cross realm case (w/ PAC)"; > messages.log
+${kadmin} modify --attributes=-no-auth-data-reqd krbtgt/${R2}@${R} || exit 1
+${kinit} --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
+for a in $enctypes; do
+ echo "Getting cross realm tickets ($a)"; > messages.log
+ ${kgetcred} -e $a ${server2}@${R2} || { ec=1 ; eval "${testfailed}"; }
+ echo " checking we we got back right ticket"
+ ${klist} | grep ${server2}@ > /dev/null || { ec=1 ; eval "${testfailed}"; }
+ echo " checking if ticket is useful"
+ ${test_ap_req} --verify-pac ${server2}@${R2} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server2}@${R2}
+done
+${kdestroy}
+
+echo "Trying x-realm TGT with kvno 0 case";
+${kinit} --password-file=${objdir}/foopassword foo@$R ||
+ { ec=1 ; eval "${testfailed}"; }
+${test_set_kvno0} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting cross realm tickets"; > messages.log
+${kgetcred} krbtgt/${R2}@${R} || { ec=1 ; eval "${testfailed}"; }
+${test_set_kvno0} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting service ticket"; > messages.log
+${kgetcred} ${server2}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying x-realm TGT with kvno 0 case with key rollover";
+${kinit} --password-file=${objdir}/foopassword foo@$R ||
+ { ec=1 ; eval "${testfailed}"; }
+${test_set_kvno0} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting cross realm tickets"; > messages.log
+${kgetcred} krbtgt/${R2}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Rolling over cross realm keys"; > messages.log
+${kadmin} cpw -r --keepold krbtgt/${R}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kadmin} cpw -r --keepold krbtgt/${R2}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kadmin} cpw -r --keepold krbtgt/${R}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${test_set_kvno0} || { ec=1 ; eval "${testfailed}"; }
+echo "Getting service ticket"; > messages.log
+echo "Start tracing kdc, then hit return"
+${kgetcred} ${server2}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying x-realm TGT with no kvno case";
+${kinit} --password-file=${objdir}/foopassword foo@$R ||
+ { ec=1 ; eval "${testfailed}"; }
+${test_set_kvno0} -n || { ec=1 ; eval "${testfailed}"; }
+echo "Getting cross realm tickets"; > messages.log
+${kgetcred} krbtgt/${R2}@${R} || { ec=1 ; eval "${testfailed}"; }
+${test_set_kvno0} -n || { ec=1 ; eval "${testfailed}"; }
+echo "Getting service ticket"; > messages.log
+${kgetcred} ${server2}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying x-realm TGT with no kvno case with key rollover";
+${kinit} --password-file=${objdir}/foopassword foo@$R ||
+ { ec=1 ; eval "${testfailed}"; }
+${test_set_kvno0} -n || { ec=1 ; eval "${testfailed}"; }
+echo "Getting cross realm tickets"; > messages.log
+${kgetcred} krbtgt/${R2}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Rolling over cross realm keys"; > messages.log
+${kadmin} cpw -r --keepold krbtgt/${R}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kadmin} cpw -r --keepold krbtgt/${R2}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kadmin} cpw -r --keepold krbtgt/${R}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${test_set_kvno0} -n || { ec=1 ; eval "${testfailed}"; }
+echo "Getting service ticket"; > messages.log
+echo "Start tracing kdc, then hit return"
+${kgetcred} ${server2}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "try all permutations"; > messages.log
+for a in $enctypes; do
+ echo "Getting client initial tickets ($a)"; > messages.log
+ ${kinit} --enctype=$a --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+ for b in $enctypes; do
+ echo "Getting tickets ($a -> $b)"; > messages.log
+ ${kgetcred} -e $b ${server}@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy} --credential=${server}@${R}
+ done
+ ${kdestroy}
+done
+
+echo "Getting client initial tickets ip based name"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
+echo "Getting ip based name tickets"; > messages.log
+${kgetcred} ${serverip}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo " checking we we got back right ticket"
+${klist} | grep ${serverip}@ > /dev/null || { ec=1 ; eval "${testfailed}"; }
+echo " checking if ticket is useful"
+${test_ap_req} ${serverip}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client initial tickets ip based name (alias)"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
+for a in ${serveripname} ${serveripname2} ; do
+ echo "Getting ip based name tickets (alias) $a"; > messages.log
+ ${kgetcred} ${a}@${R} || { ec=1 ; eval "${testfailed}"; }
+ echo " checking we we got back right ticket"
+ ${klist} | grep ${a}@ > /dev/null || { ec=1 ; eval "${testfailed}"; }
+ echo " checking if ticket is useful"
+ ${test_ap_req} --server-any ${a}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+done
+${kdestroy}
+
+echo "Getting server initial tickets"; > messages.log
+${kinit} --keytab=${keytab} ${server}@$R && { ec=1 ; eval "${testfailed}"; }
+${kadmin} modify --attributes=-disallow-client ${server} || exit 1
+${kinit} --keytab=${keytab} ${server}@$R || { ec=1 ; eval "${testfailed}"; }
+echo "Listing tickets"; > messages.log
+${klist} | grep "Principal: ${server}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting key for key that are a subset in keytab compared to kdb"
+${kinit} --keytab=${keytab} kt-des3@${R}
+${klist} | grep "Principal: kt-des3" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "initial tickets for deleted user test case"; > messages.log
+${kinit} --password-file=${objdir}/foopassword remove@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+${kadmin} delete remove@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "try getting ticket with deleted user"; > messages.log
+${kgetcred} ${server}@${R} 2> /dev/null && { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "cross realm case (deleted user)"; > messages.log
+${kinit} --password-file=${objdir}/foopassword remove2@$R2 || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} krbtgt/${R}@${R2} 2> /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kadmin} delete remove2@${R2} || exit 1
+${kgetcred} ${server}@${R} 2> /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "rename user"; > messages.log
+${kadmin} add -p foo --use-defaults rename@${R} || exit 1
+${kinit} --password-file=${objdir}/foopassword rename@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kadmin} rename rename@${R} rename2@${R} || exit 1
+${kinit} --password-file=${objdir}/foopassword rename2@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+${kadmin} delete rename2@${R} || exit 1
+
+echo "rename user to another realm"; > messages.log
+${kadmin} add -p foo --use-defaults rename@${R} || exit 1
+${kinit} --password-file=${objdir}/foopassword rename@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kadmin} rename rename@${R} rename@${R2} || exit 1
+${kinit} --password-file=${objdir}/foopassword rename@${R2} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+${kadmin} delete rename@${R2} || exit 1
+
+echo deleting all but aes enctypes on krbtgt
+${kadmin} del_enctype krbtgt/${R}@${R} ${enctype_sans_aes} || exit 1
+
+echo deleting all but des enctypes on server-des3
+${kadmin} del_enctype ${server}-des3@${R} ${enctype_sans_des3} || exit 1
+${kadmin} ext -k ${keytab} ${server}-des3@${R} || exit 1
+
+echo "try all permutations (only aes)"; > messages.log
+for a in $enctypes; do
+ echo "Getting client initial tickets ($a)"; > messages.log
+ ${kinit} --enctype=$a --password-file=${objdir}/foopassword foo@${R} ||\
+ { ec=1 ; eval "${testfailed}"; }
+ for b in $enctypes; do
+ echo "Getting tickets ($a -> $b)"; > messages.log
+ ${kgetcred} -e $b ${server}@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+ echo "Getting tickets ($a -> $b) (server des3 only)"; > messages.log
+ ${kgetcred} ${server}-des3@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${test_ap_req} ${server}-des3@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+ ${kdestroy} --credential=${server}@${R}
+ ${kdestroy} --credential=${server}-des3@${R}
+ done
+ ${kdestroy}
+done
+
+echo deleting all enctypes on krbtgt
+${kadmin} del_enctype krbtgt/${R}@${R} aes256-cts-hmac-sha1-96 || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "try initial ticket w/o and keys on krbtgt"
+${kinit} --password-file=${objdir}/foopassword foo@${R} 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+echo "adding random aes key"
+${kadmin} add_enctype -r krbtgt/${R}@${R} aes256-cts-hmac-sha1-96 || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "try initial ticket with random aes key on krbtgt"
+${kinit} --password-file=${objdir}/foopassword foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+rsa=yes
+ecdsa=yes
+pkinit=no
+if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then
+ rsa=no
+fi
+if ${hxtool} info | grep 'rand: not available' > /dev/null ; then
+ rsa=no
+fi
+if ${kinit} --help 2>&1 | grep "CA certificates" > /dev/null; then
+ pkinit=yes
+fi
+
+if ${hxtool} info | grep 'ecdsa: hcrypto null' > /dev/null ; then
+ ecdsa=no
+fi
+
+
+# If we support pkinit and have RSA, lets try that
+if test "$pkinit" = yes -a "$rsa" = yes ; then
+
+ echo "try anonymous pkinit"; > messages.log
+ ${kinit} --renewable -n @${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${kinit} --renew || { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy}
+
+ for type in "" "--pk-use-enckey"; do
+ echo "Trying pk-init (principal in certificate) $type"; > messages.log
+ ${kinit} $type -C FILE:${hx509_data}/pkinit.crt,${hx509_data}/pkinit.key bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy}
+
+ echo "Trying pk-init (principal in pki-mapping) $type"; > messages.log
+ ${kinit} $type -C FILE:${hx509_data}/pkinit.crt,${hx509_data}/pkinit.key foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy}
+
+ echo "Trying pk-init (password protected key) $type"; > messages.log
+ ${kinit} $type -C FILE:${hx509_data}/pkinit.crt,${hx509_data}/pkinit-pw.key --password-file=${objdir}/foopassword foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kgetcred} ${server}@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy}
+
+ echo "Trying pk-init (proxy cert) $type"; > messages.log
+ ${kinit} $type -C FILE:${hx509_data}/pkinit-proxy-chain.crt,${hx509_data}/pkinit-proxy.key foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy}
+
+ done
+
+ if test "$ecdsa" = yes > /dev/null ; then
+ echo "Trying pk-init (ec certificate)"
+ > messages.log
+ ${kinit} -C FILE:${hx509_data}/pkinit-ec.crt,${hx509_data}/pkinit-ec.key bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy}
+ grep 'PKINIT using ecdh' messages.log > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+ fi
+
+else
+ echo "no pkinit (pkinit: $pkinit, rsa: $rsa)"; > messages.log
+fi
+
+echo "test impersonate using rc4 based tgt"; > messages.log
+${kinit} -e arcfour-hmac-md5 --forwardable --password-file=${objdir}/foopassword ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred_imp} --impersonate=bar@${R} ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${test_ap_req} ${ps} ${keytab} ${ocache} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "tickets for impersonate test case"; > messages.log
+${kinit} --forwardable --password-file=${objdir}/foopassword ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred_imp} --impersonate=bar@${R} ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${test_ap_req} ${ps} ${keytab} ${ocache} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo " negative check"
+${kgetcred_imp} --impersonate=bar@${R} foo@${R} 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test impersonate unknown client"; > messages.log
+${kgetcred_imp} --forward --impersonate=unknown@${R} ${ps} && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test impersonate account-expired client"; > messages.log
+${kgetcred_imp} --forward --impersonate=account-expired@${R} ${ps} && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test impersonate pw-expired client"; > messages.log
+${kgetcred_imp} --forward --impersonate=pw-expired@${R} ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test delegate sensitive client"; > messages.log
+${kgetcred_imp} --forward --impersonate=sensitive@${R} ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${ocache} \
+ ${server}@${R} && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test constrained delegation (evidence from impersonation)"; > messages.log
+${kgetcred_imp} --forward --impersonate=bar@${R} ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${ocache} \
+ ${server}@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo " try using the credential"
+${test_ap_req} ${server}@${R} ${keytab} ${o2cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo " negative check"
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${ocache} \
+ bar@${R} 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test constrained delegation evidence (evidence from TGS)"; > messages.log
+echo bar > ${objdir}/barpassword
+${kinit} --cache=${icache} --forwardable --password-file=${objdir}/barpassword bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} --cache=${icache} --out-cache=${ocache} ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+# Bug #816 have a regular ticket in ${cache} for ${server} see that it isn't used
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${ocache} \
+ ${server}@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${klist2} | grep "Principal: bar@${R}" || { ec=1 ; eval "${testfailed}"; }
+echo " try using the credential"
+${test_ap_req} ${server}@${R} ${keytab} ${o2cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo " negative check"
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${ocache} \
+ bar@${R} 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test constrained delegation with foreign client (evidence from TGS)"; > messages.log
+# We can't test foreign client with evidence from S4U2Self, since Heimdal doesn't support it yet
+rm -f ocache.krb5
+${kinit} --cache=${icache} --forwardable --password-file=${objdir}/foopassword foo@${R2} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} --cache=${icache} --out-cache=${ocache} ${ps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${ocache} \
+ ${server}@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${klist2} | grep "Principal: foo@${R2}" || { ec=1 ; eval "${testfailed}"; }
+echo " try using the credential"
+${test_ap_req} ${server}@${R} ${keytab} ${o2cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test constrained delegation impersonation (non forward)"; > messages.log
+rm -f ocache.krb5
+${kimpersonate} -s ${ps} -c bar@${R} -t ${aesenctype} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} --out-cache=${o2cache} --delegation-credential-cache=${ocache} ${server}@${R} > /dev/null 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test constrained delegation evidence (evidence from AS)"; > messages.log
+# This fails because we don't add PAC ticket-signature in AS-REP (as Windows).
+${kinit} --cache=${ocache} --password-file=${objdir}/barpassword \
+ --forwardable --server=${ps} bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} --delegation-credential-cache=${ocache} ${server}@${R} && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test constrained delegation impersonation (missing PAC)"; > messages.log
+rm -f ocache.krb5
+${kimpersonate} -s ${ps} -c bar@${R} -t ${aesenctype} -f forwardable || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} --out-cache=${o2cache} --delegation-credential-cache=${ocache} ${server}@${R} > /dev/null 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+
+${kdestroy}
+
+echo "test constrained delegation NOT trusted-for-delegation (evidence from TGS)"; > messages.log
+
+${kinit} --forwardable --password-file=${objdir}/foopassword ${rps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kinit} --cache=${icache} --forwardable --password-file=${objdir}/barpassword bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} --cache=${icache} --out-cache=${ocache} ${rps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${ocache} \
+ ${server}@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${klist2} | grep "Principal: bar@${R}" || { ec=1 ; eval "${testfailed}"; }
+${test_ap_req} ${server}@${R} ${keytab} ${o2cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test constrained delegation NOT trusted-for-delegation (evidence from impersonate, negative)"; > messages.log
+rm -f ocache.krb5
+${kgetcred_imp} --impersonate=bar@${R} ${rps} || \
+ { ec=1 ; eval "${testfailed}"; }
+${test_ap_req} ${rps} ${keytab} ${ocache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${ocache} \
+ ${server}@${R} && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "test constrained delegation bronze-bit attack, aka CVE-2020-17049"; > messages.log
+
+KRB5CCNAME=${ocache} KRB5_KTNAME=${keytab} ${test_mkforwardable} ${rps} ${icache} || \
+{ ec=1 ; eval "${testfailed}"; }
+
+${kgetcred} \
+ --out-cache=${o2cache} \
+ --delegation-credential-cache=${icache} \
+ ${server}@${R} && \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "check renewing" > messages.log
+${kinit} --renewable --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "kinit -R"
+${kinit} -R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "check renewing MIT interface" > messages.log
+${kinit} --renewable --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "test_renew"
+env KRB5CCNAME=${cache} ${test_renew} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "checking server aliases"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting tickets"; > messages.log
+${kgetcred} ${alias1}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${alias2}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo " verify entry in keytab"
+${test_ap_req} ${alias1}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo " verify entry in keytab with any"
+${test_ap_req} --server-any ${alias1}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo " verify failure with alias entry"
+${test_ap_req} ${alias2}@${R} ${keytab} ${cache} 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+echo " verify alias entry in keytab with any"
+${test_ap_req} --server-any ${alias2}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "testing removal of keytab"
+${ktutil} -k ${keytab} destroy || { ec=1 ; eval "${testfailed}"; }
+test -f ${keytabfile} && { ec=1 ; eval "${testfailed}"; }
+
+echo "Checking client pw expire"; > messages.log
+${kinit} --password-file=${objdir}/foopassword \
+ pw-expire@${R} 2>kinit-log.tmp|| \
+ { ec=1 ; eval "${testfailed}"; }
+grep 'Your password will expire' kinit-log.tmp > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+echo " kinit passes"
+${test_gic} --client=pw-expire@${R} --password=foo > kinit-log.tmp 2>/dev/null
+${EGREP} "^e type: 6" kinit-log.tmp > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+echo " test_gic passes"
+${kdestroy}
+
+echo "Checking password expiration" ; > messages.log
+
+kinitpty=${objdir}/foopassword.rkpty
+cat > ${kinitpty} <<EOF
+expect Password
+password foo\n
+expect Password has expired
+expect New password
+password Foobar11\n
+expect password
+password Foobar11\n
+expect Success: Password changed
+EOF
+
+echo "Checking client pw expire"; > messages.log
+${rkpty} ${kinitpty} ${kinit} pw-expired@${R}|| \
+ { ec=1 ; eval "${testfailed}"; }
+
+${kdestroy}
+
+
+echo "killing kdc (${kdcpid}) kpasswdd (${kpasswddpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+sh ${leaks_kill} kpasswdd $kpasswddpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-keys.in b/third_party/heimdal/tests/kdc/check-keys.in
new file mode 100644
index 0000000..6784bb5
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-keys.in
@@ -0,0 +1,104 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="."
+
+. ${env_setup}
+
+srcdir="${top_srcdir}/tests/kdc"
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+principal=host/datan.test.h5l.se@${R}
+
+kadmin="${kadmin} -l -r $R"
+
+CIN=${srcdir}/krb5.conf.keys.in
+COUT=${objdir}/krb5.conf.keys
+
+sedvars="-e s,[@]srcdir[@],${srcdir},g -e s,[@]objdir[@],${objdir},g"
+
+KRB5_CONFIG="${COUT}"
+export KRB5_CONFIG
+
+rm -f ${COUT}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+rm -f messages.log
+
+sed -e 's/@keys@/v5/' \
+ ${sedvars} < ${CIN} > ${COUT}
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} add -p foo --use-defaults ${principal} || exit 1
+
+${kadmin} cpw -p foo ${principal} || exit 1
+
+sed -e 's/@keys@/v4/' \
+ ${sedvars} < ${CIN} > ${COUT}
+${kadmin} cpw -p foo ${principal} || exit 1
+
+sed -e 's/@keys@/v4 v5/' \
+ ${sedvars} < ${CIN} > ${COUT}
+${kadmin} cpw -p foo ${principal} || exit 1
+
+sed -e 's/@keys@/v5 v4/' \
+ ${sedvars} < ${CIN} > ${COUT}
+${kadmin} cpw -p foo ${principal} || exit 1
+
+sed -e 's/@keys@/des:pw-salt:/' \
+ ${sedvars} < ${CIN} > ${COUT}
+${kadmin} cpw -p foo ${principal} || exit 1
+
+if [ 'X@ENABLE_AFS_STRING_TO_KEY@' = "X1" ]; then
+ sed -e 's/@keys@/des-cbc-crc:afs3-salt:test.h5l.se/' \
+ ${sedvars} < ${CIN} > ${COUT}
+ ${kadmin} cpw -p foo ${principal} || exit 1
+
+ sed -e 's/@keys@/des:afs3-salt:test.h5l.se/' \
+ ${sedvars} < ${CIN} > ${COUT}
+ ${kadmin} cpw -p foo ${principal} || exit 1
+fi
+
+exit 0
diff --git a/third_party/heimdal/tests/kdc/check-kinit.in b/third_party/heimdal/tests/kdc/check-kinit.in
new file mode 100644
index 0000000..c6cb23f
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-kinit.in
@@ -0,0 +1,149 @@
+#!/bin/bash
+#
+# Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+KRB5_CONFIG="${objdir}/krb5-kinit.conf"
+export KRB5_CONFIG
+KRB5CCNAME="${objdir}/foocc"
+export KRB5CCNAME
+
+testfailed="echo test failed; exit 1"
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+
+port=@port@
+pwport=@pwport@
+
+kinit="${kinit} --password-file=${objdir}/foopassword ${afs_no_afslog} -c ${objdir}/foocc"
+klist="${klist} -c ${objdir}/foocc"
+kgetcred="${kgetcred} -c ${objdir}/foocc"
+kdestroy="${kdestroy} ${afs_no_unlog}"
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+
+
+cache="FILE:${objdir}/cache.krb5"
+keytabfile=${objdir}/server.keytab
+keytab="FILE:${keytabfile}"
+
+> messages.log
+
+num_concurrent=50
+num_princs=20
+torture_time=200
+cred_life=$((torture_time / 10))
+cred_renew_life=$((torture_time / 2))
+out=${objdir}/out-kinit-torture-kgetcred
+kinit_out=${objdir}/out-kinit-torture-kinit
+
+parent_shell_proc=$$
+
+if (($# == 0)); then
+
+ echo "This is a MANUAL test."
+
+ rm -f ${keytabfile}
+ rm -f current-db*
+ rm -f out-*
+ rm -f mkey.file*
+
+ cp "${objdir}/krb5.conf" "${objdir}/krb5-kinit.conf"
+
+ echo "Creating database"
+ ${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+ echo "Adding foo"
+ ${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+
+ echo "Creating torture principals"
+ for i in $(seq 0 $((num_princs - 1)) ); do
+ ${kadmin} add -r --use-defaults svc${i}@${R} || exit 1
+ done
+
+ echo "Doing database check"
+ ${kadmin} check ${R} || exit 1
+
+ echo foo > ${objdir}/foopassword
+
+ echo Starting kdc ; > messages.log
+ ${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+ kdcpid=`getpid kdc`
+
+ trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+
+ ec=0
+else
+ echo "begin torture (output in $out)"
+ secs=$(date +%s)
+ cat /dev/null > "$out"
+ while (($(date +%s) < (secs + torture_time) )); do
+ echo .
+ for i in $(seq 0 1000); do
+ printf '%d\n' $((i % num_princs))
+ done | xargs -P $num_concurrent -I '{}' ${kgetcred} "svc{}@${R}"
+ ${klist} -v || exit 1
+ if ! kill -0 $parent_shell_proc; then
+ printf 'Parent shell script exited; exiting'
+ exit 1
+ grep 'Matching credential .* not found' messages.log > /dev/null &&
+ echo "THAT DID NOT WORK RIGHT"
+ fi
+ sleep 5
+ done
+ ${klist} -v
+ exit 0
+fi
+
+echo "checking that we have tickets"
+${kinit} -l $cred_life -r $cred_renew_life foo@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist} -v || { ec=1 ; eval "${testfailed}"; }
+echo "torturing"
+${kinit} -l $cred_life -r $cred_renew_life foo@${R} "$0" torture-me || { ec=1 ; eval "${testfailed}"; }
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-kpasswdd.in b/third_party/heimdal/tests/kdc/check-kpasswdd.in
new file mode 100644
index 0000000..39f12e1
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-kpasswdd.in
@@ -0,0 +1,194 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+testfailed="echo test failed; cat messages.log; exit \$ec"
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+R2=TEST2.H5L.SE
+
+port=@port@
+pwport=@pwport@
+
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+kpasswdd="${kpasswdd} --addresses=localhost -p $pwport"
+
+server=host/datan.test.h5l.se
+cache="FILE:${objdir}/cache.krb5"
+keytabfile=${objdir}/server.keytab
+keytab="FILE:${keytabfile}"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist="${klist} -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo "Creating database for $R"
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+${kadmin} add -p kaka --use-defaults ${server}@${R} || exit 1
+${kadmin} ext -k ${keytab} ${server}@${R} || exit 1
+
+echo "Creating database for ${R2}"
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R2} || exit 1
+
+${kadmin} add -p foo --use-defaults bar@${R2} || exit 1
+
+echo "Doing database check for ${R} ${R2}"
+${kadmin} check ${R} || exit 1
+${kadmin} check ${R2} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo Starting kdc ; > messages.log
+env ${HEIM_MALLOC_DEBUG} ${kdc} --detach --testing ||
+ { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+echo Starting kpasswdd
+env ${HEIM_MALLOC_DEBUG} ${kpasswdd} --detach ||
+ { echo "kpasswdd failed to start"; exit 1; }
+kpasswddpid=`getpid kpasswdd`
+
+trap "kill -9 ${kdcpid} ${kpasswddpid}; echo signal killing kdc; exit \$ec;" EXIT
+
+ec=0
+
+echo "Getting client initial tickets"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting tickets"; > messages.log
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Listing tickets"; > messages.log
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "checking ${R}"
+
+pw=ak4unandsop39NuJ
+
+echo "Changing password"
+cat > cpw.tmp <<EOF
+expect Password
+password foo\n
+expect New password
+send ${pw}\n
+expect New password
+send ${pw}\n
+expect Success
+EOF
+
+${rkpty} cpw.tmp env ${kpasswd} foo@${R} || \
+ { ec=$? ; eval "${testfailed}"; }
+
+rm cpw.tmp
+
+echo ${pw} > ${objdir}/barpassword
+
+
+echo "Getting client initial tickets for ${R}"; > messages.log
+${kinit} --password-file=${objdir}/barpassword foo@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting tickets"; > messages.log
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Listing tickets"; > messages.log
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+
+echo "checking ${R2}"
+
+cat > cpw.tmp <<EOF
+expect Password
+password foo\n
+expect New password
+send ${pw}\n
+expect New password
+send ${pw}\n
+expect Success
+EOF
+
+${rkpty} cpw.tmp ../../kpasswd/kpasswd bar@${R2} || \
+ { ec=$? ; eval "${testfailed}"; }
+
+rm cpw.tmp
+
+
+echo "Getting client initial tickets for ${R2}"; > messages.log
+${kinit} --password-file=${objdir}/barpassword bar@${R2} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+
+echo "killing kdc (${kdcpid} ${kpasswddpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+sh ${leaks_kill} kpasswdd $kpasswddpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-pkinit.in b/third_party/heimdal/tests/kdc/check-pkinit.in
new file mode 100644
index 0000000..571a64e
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-pkinit.in
@@ -0,0 +1,393 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+
+port=@port@
+
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+
+server=host/datan.test.h5l.se
+cache="FILE:${objdir}/cache.krb5"
+keyfile="${hx509_data}/key.der"
+keyfile2="${hx509_data}/key2.der"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klistjson="${klist} --json -c $cache"
+klistplain="${klist} -c $cache"
+klist="${klist} --hidden -v -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+kx509="${kx509} -c $cache"
+
+KRB5_CONFIG="${objdir}/krb5-pkinit.conf"
+export KRB5_CONFIG
+HEIM_PIDFILE_DIR=$objdir
+export HEIM_PIDFILE_DIR
+HEIM_IPC_DIR=$objdir
+export HEIM_IPC_DIR
+
+
+rsa=yes
+pkinit=no
+if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then
+ rsa=no
+fi
+if ${hxtool} info | grep 'rand: not available' > /dev/null ; then
+ rsa=no
+fi
+
+if ${kinit} --help 2>&1 | grep "CA certificates" > /dev/null; then
+ pkinit=yes
+fi
+
+# If we doesn't support pkinit and have RSA, give up
+if test "$pkinit" != yes -o "$rsa" != yes ; then
+ exit 77
+fi
+
+
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} modify --max-ticket-life=5d krbtgt/${R}@${R} || exit 1
+${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+${kadmin} add -p bar --use-defaults bar@${R} || exit 1
+${kadmin} add -p baz --use-defaults baz@${R} || exit 1
+${kadmin} add -p foo --use-defaults host/server.test.h5l.se@${R} || exit 1
+${kadmin} modify --alias=baz2\\@test.h5l.se@${R} baz@${R} || exit 1
+${kadmin} modify --pkinit-acl="CN=baz,DC=test,DC=h5l,DC=se" baz@${R} || exit 1
+
+${kadmin} add -p kaka --use-defaults ${server}@${R} || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+
+# XXX Do not use committed, in-tree private keys or certificates!
+# XXX Add hxtool command to generate a private key w/o generating a CSR
+# XXX Use hxtool to generate a fresh private key
+# XXX Use hxtool to generate self-signed CA certs
+# XXX Use PEM-FILE and store private key and certificate in same file
+# XXX Update krb5.conf.in to use ${objdir}-relative keys and certificates
+
+echo "Setting up certificates"
+${hxtool} request-create \
+ --subject="CN=kdc,DC=test,DC=h5l,DC=se" \
+ --key=FILE:${keyfile2} \
+ req-kdc.der || exit 1
+${hxtool} request-create \
+ --subject="CN=bar,DC=test,DC=h5l,DC=se" \
+ --key=FILE:${keyfile2} \
+ req-pkinit.der || exit 1
+${hxtool} request-create \
+ --subject="CN=baz,DC=test,DC=h5l,DC=se" \
+ --key=FILE:${keyfile2} \
+ req-pkinit2.der || exit 1
+
+echo "issue self-signed ca cert"
+${hxtool} issue-certificate \
+ --self-signed \
+ --issue-ca \
+ --ca-private-key=FILE:${keyfile} \
+ --subject="CN=CA,DC=test,DC=h5l,DC=se" \
+ --certificate="FILE:ca.crt" || exit 1
+
+echo "issue kdc certificate"
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-kdc" \
+ --pk-init-principal="krbtgt/TEST.H5L.SE@TEST.H5L.SE" \
+ --req="PKCS10:req-kdc.der" \
+ --certificate="FILE:kdc.crt" || exit 1
+
+echo "issue user certificate (pkinit san)"
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --pk-init-principal="bar@TEST.H5L.SE" \
+ --req="PKCS10:req-pkinit.der" \
+ --lifetime=7d \
+ --certificate="FILE:pkinit.crt" || exit 1
+
+echo "issue user certificate (pkinit san; synthetic principal)"
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --pk-init-principal="synthetized@TEST.H5L.SE" \
+ --req="PKCS10:req-pkinit.der" \
+ --lifetime=7d \
+ --certificate="FILE:pkinit-synthetic.crt" || exit 1
+
+echo "issue user 2 certificate (no san)"
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --req="PKCS10:req-pkinit2.der" \
+ --certificate="FILE:pkinit2.crt" || exit 1
+
+echo "issue user 3 certificate (ms san)"
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --ms-upn="bar@test.h5l.se" \
+ --req="PKCS10:req-pkinit2.der" \
+ --certificate="FILE:pkinit3.crt" || exit 1
+
+echo "issue user 3 certificate (ms san, baz2)"
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --ms-upn="baz2\\@test.h5l.se@${R}" \
+ --req="PKCS10:req-pkinit2.der" \
+ --certificate="FILE:pkinit4.crt" || exit 1
+
+echo "issue self-signed kx509 template cert"
+${hxtool} issue-certificate \
+ --self-signed \
+ --ca-private-key=FILE:${keyfile} \
+ --subject='CN=${principal-component0},DC=test,DC=h5l,DC=se' \
+ --certificate="FILE:kx509-template.crt" || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo Starting kdc ; > messages.log
+KRB5_CONFIG="${objdir}/krb5-pkinit2.conf"
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap 'kill -9 ${kdcpid}; echo signal killing kdc; cat ca.crt kdc.crt pkinit.crt pkinit-synthetic.crt; exit 1;' EXIT
+
+ec=0
+
+echo "Trying pk-init (principal in cert; longer max_life)"; > messages.log
+base="${objdir}"
+${kinit} --lifetime=5d -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist}
+if jq --version >/dev/null 2>&1 && jq -ne true >/dev/null 2>&1; then
+ ${klistjson} |
+ jq -e '(((.tickets[0].Expires|
+ strptime("%b %d %H:%M:%S %Y")|mktime) - now) / 86400) |
+ (floor < 4)' >/dev/null &&
+ { ec=1 ; eval "${testfailed}"; }
+fi
+${kdestroy}
+
+echo "Trying pk-init (principal in cert; synthetic)"; > messages.log
+base="${objdir}"
+${kinit} --lifetime=5d -C FILE:${base}/pkinit-synthetic.crt,${keyfile2} synthetized@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist}
+${kdestroy}
+
+echo "Restarting kdc ($kdcpid)"
+sh ${leaks_kill} kdc $kdcpid || ec=1
+KRB5_CONFIG="${objdir}/krb5-pkinit.conf"
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+echo "Trying pk-init (principal in cert)"; > messages.log
+base="${objdir}"
+${kinit} -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist}
+if jq --version >/dev/null 2>&1 && jq -ne true >/dev/null 2>&1; then
+ ${klistjson} |
+ jq -e '(((.tickets[0].Expires|
+ strptime("%b %d %H:%M:%S %Y")|mktime) - now) / 86400) |
+ (floor > 1)' >/dev/null &&
+ { ec=1 ; eval "${testfailed}"; }
+fi
+${kdestroy}
+
+echo "Trying pk-init (principal in cert; longer max_life from cert ext)"; > messages.log
+# Re-issue cert with --pkinit-max-life=7d
+${hxtool} issue-certificate \
+ --ca-certificate=FILE:$objdir/ca.crt,${keyfile} \
+ --type="pkinit-client" \
+ --pk-init-principal="bar@TEST.H5L.SE" \
+ --req="PKCS10:req-pkinit.der" \
+ --lifetime=7d \
+ --pkinit-max-life=7d \
+ --certificate="FILE:pkinit.crt" || exit 1
+base="${objdir}"
+${kinit} --lifetime=5d -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${klist}
+if jq --version >/dev/null 2>&1 && jq -ne true >/dev/null 2>&1; then
+ ${klistjson} |
+ jq -e '(((.tickets[0].Expires|
+ strptime("%b %d %H:%M:%S %Y")|mktime) - now) / 86400) |
+ (floor < 4)' >/dev/null &&
+ { ec=1 ; eval "${testfailed}"; }
+fi
+
+echo "Check kx509 certificate acquisition"
+${kx509} -s || { ec=1 ; eval "${testfailed}"; }
+${kx509} -o PEM-FILE:${objdir}/kx509.pem || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Check PKINIT w/ kx509 certificate"
+${kinit} -C PEM-FILE:${objdir}/kx509.pem bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Trying pk-init (principal in pki-mapping file) "; > messages.log
+${kinit} -C FILE:${base}/pkinit.crt,${keyfile2} foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying pk-init (principal subject in DB)"; > messages.log
+${kinit} -C FILE:${base}/pkinit2.crt,${keyfile2} baz@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying pk-init (ms upn)"; > messages.log
+${kinit} -C FILE:${base}/pkinit3.crt,${keyfile2} bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying pk-init (ms upn, enterprise)"; > messages.log
+${kinit} --canonicalize --enterprise \
+ -C FILE:${base}/pkinit4.crt,${keyfile2} baz2@test.h5l.se || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying pk-init (ms upn, enterprise, pk-enterprise)"; > messages.log
+${kinit} --canonicalize \
+ --pk-enterprise \
+ -C FILE:${base}/pkinit4.crt,${keyfile2} ${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+KRB5_CONFIG="${objdir}/krb5-pkinit-win.conf"
+export KRB5_CONFIG
+
+echo "Duplicated tests, now in windows 2000 mode"
+
+echo "Trying pk-init (principal in cert)"; > messages.log
+base="${objdir}"
+${kinit} -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying pk-init (principal in pki-mapping file) "; > messages.log
+${kinit} -C FILE:${base}/pkinit.crt,${keyfile2} foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying pk-init (principal subject in DB)"; > messages.log
+${kinit} -C FILE:${base}/pkinit2.crt,${keyfile2} baz@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Trying pk-init (ms upn)"; > messages.log
+${kinit} -C FILE:${base}/pkinit3.crt,${keyfile2} bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+
+KRB5_CONFIG="${objdir}/krb5-pkinit.conf"
+export KRB5_CONFIG
+
+echo "Trying PKCS11 support"
+
+cat > test-rc-file.rc <<EOF
+certificate cert User certificate FILE:${base}/pkinit.crt,${keyfile2}
+app-fatal true
+EOF
+
+SOFTPKCS11RC="test-rc-file.rc"
+export SOFTPKCS11RC
+
+dir=${base}/../../lib/hx509
+file=
+
+for a in libhx509.so .libs/libhx509.so libhx509.dylib .libs/libhx509.dylib ; do
+ if [ -f $dir/$a ] ; then
+ file=$dir/$a
+ break
+ fi
+done
+
+if [ X"$file" != X -a @DLOPEN@ ] ; then
+
+ echo "Trying pk-init (principal in pki-mapping file) "; > messages.log
+ ${kinit} -C PKCS11:${file} foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+ ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
+ ${kdestroy}
+
+fi
+
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || ec=1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-referral.in b/third_party/heimdal/tests/kdc/check-referral.in
new file mode 100644
index 0000000..49f6a52
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-referral.in
@@ -0,0 +1,301 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+
+. ${env_setup}
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+d=test.h5l.se
+d2=xtst.heim.example
+R=TEST.H5L.SE
+R2=XTST.HEIM.EXAMPLE
+
+# $service1 will be a hard alias of $service2
+service1=ldap/host.${d}:389
+service2=ldap/host.${d2}:389
+# $service3 and $service4 will have soft aliases referrals from each
+# other's realms
+service3=host/foohost.${d}
+service4=host/barhost.${d2}
+# $service5 and $service6 will be hardaliases
+service5=host/thing1.${d}
+service6=host/thing1.${d2}
+# $service7 and $service8 will be hardaliases in the opposite direction
+service7=host/thing2.${d}
+service8=host/thing2.${d2}
+
+port=@port@
+
+kadmin="${kadmin} -l -r $R"
+kdc="${kdc} --addresses=localhost -P $port"
+
+cache="FILE:${objdir}/cache.krb5"
+
+kinit="${kinit} -c $cache ${afs_no_afslog}"
+klist="${klist} -c $cache"
+kgetcred="${kgetcred} -c $cache"
+kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+keytabfile=${objdir}/server.keytab
+keytab="FILE:${keytabfile}"
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+KRB5CCNAME=$cache
+export KRB5CCNAME
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R2} || exit 1
+
+${kadmin} add -r --use-defaults WELLKNOWN/REFERRALS/TARGET@${R} || exit 1
+${kadmin} add -r --use-defaults WELLKNOWN/REFERRALS/TARGET@${R2} || exit 1
+
+# User 'foo' gets two aliases in the same realm, and one in the other
+${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+${kadmin} add_alias foo@${R} foo@${R2} alias1 alias2 || exit 1
+${kadmin} get foo@${R} | grep alias1@${R} >/dev/null || exit 1
+${kadmin} get foo@${R} | grep alias2@${R} >/dev/null || exit 1
+${kadmin} get foo@${R} | grep foo@${R2} >/dev/null || exit 1
+
+# service1 is an alias of service2, in different realms
+${kadmin} add -p foo --use-defaults ${service2}@${R2} || exit 1
+${kadmin} add_alias ${service2}@${R2} ${service1}@${R} || exit 1
+${kadmin} get ${service2}@${R2} | grep ${service1}@${R} >/dev/null || exit 1
+
+# service3 and service4 get soft aliases in each other's realms
+${kadmin} add -p foo --use-defaults ${service3}@${R} || exit 1
+${kadmin} add -p foo --use-defaults ${service4}@${R2} || exit 1
+${kadmin} add_alias WELLKNOWN/REFERRALS/TARGET@${R2} ${service4}@${R} || exit 1
+${kadmin} add_alias WELLKNOWN/REFERRALS/TARGET@${R} ${service3}@${R2} || exit 1
+
+# service6 is a hard alias of service5
+${kadmin} add -p foo --use-defaults ${service5}@${R} || exit 1
+${kadmin} add_alias ${service5}@${R} ${service6}@${R2} || exit 1
+
+# service8 is a hard alias of service7, but in the opposite direction
+${kadmin} add -p foo --use-defaults ${service7}@${R2} || exit 1
+${kadmin} add_alias ${service5}@${R} ${service8}@${R} || exit 1
+
+${kadmin} add -p foo --use-defaults bar@${R} || exit 1
+${kadmin} add -p foo --use-defaults 'baz\@realm.foo@'${R} || exit 1
+
+${kadmin} add -p cross1 --use-defaults krbtgt/${R2}@${R} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R}@${R2} || exit 1
+
+${kadmin} ext -k ${keytab} krbtgt/${R}@${R} || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+${kadmin} check ${R2} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo Starting kdc ; > messages.log
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+
+ec=0
+
+
+echo "Getting client bar"; > messages.log
+${kinit} --password-file=${objdir}/foopassword bar@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "Principal: bar@${R}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client baz"; > messages.log
+${kinit} --password-file=${objdir}/foopassword 'baz\@realm.foo@'${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep 'Principal: baz' > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+
+
+echo "Test AS-REQ"
+
+echo "Getting client (no canon)"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "Principal: foo@${R}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client client tickets (default realm, enterprisename)"; > messages.log
+${kinit} --canonicalize --enterprise \
+ --password-file=${objdir}/foopassword foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "Principal: foo@${R}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal inside the PAC"
+${test_ap_req} krbtgt/${R}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client alias1 tickets"; > messages.log
+${kinit} --canonicalize --enterprise \
+ --password-file=${objdir}/foopassword foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "Principal: foo@${R}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal inside the PAC"
+${test_ap_req} krbtgt/${R}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+
+echo "Getting client alias2 tickets"; > messages.log
+${kinit} --canonicalize --enterprise \
+ --password-file=${objdir}/foopassword alias2@${R}@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "Principal: foo@${R}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal inside the PAC"
+${test_ap_req} krbtgt/${R}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client alias1 tickets (non canon case)"; > messages.log
+${kinit} --password-file=${objdir}/foopassword alias1@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "Principal: alias1@${R}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal inside the PAC"
+${test_ap_req} krbtgt/${R}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service2}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service1}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client foo@${R2} tickets (non canon case)"; > messages.log
+${kinit} --password-file=${objdir}/foopassword foo@${R2} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "Principal: foo@${R2}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal inside the PAC"
+${test_ap_req} krbtgt/${R}@${R} ${keytab} ${cache} || \
+ { ec=1 ; eval "${testfailed}"; }
+echo "Getting various service tickets using foo@${R2} client"
+${kgetcred} ${service2}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service1}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service1}@${R2} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service2}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service3}@ || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service4}@ || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service5}@ || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service6}@ || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service7}@ || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service8}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client alias2 tickets (removed)"; > messages.log
+${kadmin} modify --alias=alias1 foo@${R} || { ec=1 ; eval "${testfailed}"; }
+${kinit} --canonicalize --enterprise \
+ --password-file=${objdir}/foopassword \
+ alias2@${R}@${R} > /dev/null 2>/dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Remove alias"
+${kadmin} modify --alias= foo@${R} || { ec=1 ; eval "${testfailed}"; }
+
+echo "Test server referrals"
+
+echo "Getting client for ${service2}@${R} (tgs kdc referral)"
+> messages.log
+${kinit} --password-file=${objdir}/foopassword foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} --canonicalize ${service2}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service3}@${R} || { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service4}@ || { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "${service2}@${R2}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${klist} | grep "${service4}@${R}" > /dev/null && \
+ { ec=1 ; eval "${testfailed}"; }
+${klist} | grep "${service4}@${R2}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+echo "Getting client for ${service2}@${R2} (tgs client side guessing)"
+> messages.log
+${kinit} --password-file=${objdir}/foopassword foo@${R} || \
+ { ec=1 ; eval "${testfailed}"; }
+${kgetcred} ${service2}@${R2} ||
+ { ec=1 ; eval "${testfailed}"; }
+echo "checking that we got back right principal"
+${klist} | grep "${service2}@${R2}" > /dev/null || \
+ { ec=1 ; eval "${testfailed}"; }
+${kdestroy}
+
+
+echo "killing kdc (${kdcpid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-tester.in b/third_party/heimdal/tests/kdc/check-tester.in
new file mode 100644
index 0000000..83b48ba
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-tester.in
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top_builddir="@top_builddir@"
+env_setup="@env_setup@"
+objdir="@objdir@"
+srcdir="@srcdir@"
+
+. ${env_setup}
+
+KRB5_CONFIG="${1-${objdir}/krb5.conf}"
+export KRB5_CONFIG
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+# Do not run in GutHub valgrind builds -- too slow / not necessary
+[ -n "$CHECK_TESTER_NO_VALGRIND" ] && exit 77
+
+R=TEST.H5L.SE
+
+keytabfile=${objdir}/server.keytab
+keytab="FILE:${keytabfile}"
+keyfile="${hx509_data}/key.der"
+keyfile2="${hx509_data}/key2.der"
+
+kadmin="${kadmin} -l -r $R"
+
+server=host/datan.test.h5l.se
+
+rsa=yes
+pkinit=no
+if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then
+ rsa=no
+fi
+if ${hxtool} info | grep 'rand: not available' > /dev/null ; then
+ rsa=no
+fi
+
+if ${kinit} --help 2>&1 | grep "CA certificates" > /dev/null; then
+ pkinit=yes
+fi
+
+# If we doesn't support pkinit and have RSA, give up
+if test "$rsa" != yes ; then
+ pkinit=no
+fi
+
+rm -f ${keytabfile}
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} add -p foo --use-defaults ${server}@${R} || exit 1
+${kadmin} add -p foo --use-defaults foo@${R} || exit 1
+${kadmin} ext -k ${keytab} foo@${R} || exit 1
+${kadmin} ext -k ${keytab} ${server}@${R} || exit 1
+
+echo "password"
+${kdc_tester} ${srcdir}/kdc-tester1.json > out-log 2>&1 || exit 1
+sed 's/^/ /' out-log
+
+echo "keytab"
+${kdc_tester} ${srcdir}/kdc-tester2.json > out-log 2>&1 || exit 1
+sed 's/^/ /' out-log
+
+echo "FAST + keytab"
+${kdc_tester} ${srcdir}/kdc-tester3.json > out-log 2>&1 || exit 1
+sed 's/^/ /' out-log
+
+
+if test "$pkinit" = yes ; then
+
+ echo "pkinit"
+ ${kdc_tester} ${objdir}/kdc-tester4.json > out-log 2>&1 || exit 1
+ sed 's/^/ /' out-log
+
+fi
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/check-uu.in b/third_party/heimdal/tests/kdc/check-uu.in
new file mode 100644
index 0000000..ef831ca
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/check-uu.in
@@ -0,0 +1,131 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+env_setup="@env_setup@"
+objdir="@objdir@"
+srcdir="@srcdir@"
+
+testfailed="echo test failed; cat messages.log; exit 1"
+
+. ${env_setup}
+
+# If there is no useful db support compiled in, disable test
+${have_db} || exit 77
+
+R=TEST.H5L.SE
+
+uuspid=
+
+port=@port@
+
+kadmin="${TESTS_ENVIRONMENT} ../../kadmin/kadmin -l -r $R"
+kdc="${TESTS_ENVIRONMENT} ../../kdc/kdc --addresses=localhost -P $port"
+
+cache1="FILE:${objdir}/cache1.krb5"
+cache2="FILE:${objdir}/cache2.krb5"
+
+kinit1="${TESTS_ENVIRONMENT} ../../kuser/kinit -c $cache1 ${afs_no_afslog}"
+kinit2="${TESTS_ENVIRONMENT} ../../kuser/kinit -c $cache2 ${afs_no_afslog}"
+kdestroy1="${TESTS_ENVIRONMENT} ../../kuser/kdestroy -c $cache1 ${afs_no_unlog}"
+kdestroy2="${TESTS_ENVIRONMENT} ../../kuser/kdestroy -c $cache2 ${afs_no_unlog}"
+uu_server="${TESTS_ENVIRONMENT} ../../appl/test/uu_server"
+uu_client="${TESTS_ENVIRONMENT} ../../appl/test/uu_client"
+
+KRB5_CONFIG="${objdir}/krb5.conf"
+export KRB5_CONFIG
+
+rm -f current-db*
+rm -f out-*
+rm -f mkey.file*
+
+> messages.log
+
+echo Creating database
+${kadmin} \
+ init \
+ --realm-max-ticket-life=1day \
+ --realm-max-renewable-life=1month \
+ ${R} || exit 1
+
+${kadmin} add -p foo --use-defaults user1@${R} || exit 1
+${kadmin} add -p foo --use-defaults user2@${R} || exit 1
+
+echo "Doing database check"
+${kadmin} check ${R} || exit 1
+
+echo foo > ${objdir}/foopassword
+
+echo Starting kdc ; > messages.log
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+trap "kill -9 ${kdcpid} ${uuspid}; echo signal killing kdc; exit 1;" EXIT
+
+ec=0
+
+echo "Getting client initial tickets user1"; > messages.log
+${kinit1} --password-file=${objdir}/foopassword user1@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+
+echo "Getting client initial tickets user2"; > messages.log
+${kinit2} --password-file=${objdir}/foopassword user2@$R || \
+ { ec=1 ; eval "${testfailed}"; }
+
+
+echo "starting uu server (using user1)"
+KRB5CCNAME=$cache1 ${uu_server} > uuserver.log &
+uuspid=$!
+sleep 5
+
+echo "trying to contact server with client (using user2)"
+KRB5CCNAME=$cache2 ${uu_client} localhost > messages.log 2>&1 || \
+ { ec=1; eval "${testfailed}"; }
+
+sleep 5
+
+echo "checking if server got the right message"
+cmp uuserver.log ${srcdir}/uuserver.txt || \
+ { ec=1; eval "${testfailed}"; }
+
+uuspid=""
+
+${kdestroy1}
+${kdestroy2}
+
+echo "killing kdc uu_server (${kdcpid} ${uuspid})"
+sh ${leaks_kill} kdc $kdcpid || exit 1
+
+
+trap "" EXIT
+
+exit $ec
diff --git a/third_party/heimdal/tests/kdc/donotexists.txt b/third_party/heimdal/tests/kdc/donotexists.txt
new file mode 100644
index 0000000..5294397
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/donotexists.txt
@@ -0,0 +1 @@
+kadmin: get doesnotexists@TEST.H5L.SE: Principal does not exist
diff --git a/third_party/heimdal/tests/kdc/hdb-mitdb b/third_party/heimdal/tests/kdc/hdb-mitdb
new file mode 100644
index 0000000..00fefb9
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/hdb-mitdb
Binary files differ
diff --git a/third_party/heimdal/tests/kdc/hdb-mitdb.kadm5 b/third_party/heimdal/tests/kdc/hdb-mitdb.kadm5
new file mode 100644
index 0000000..41663b9
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/hdb-mitdb.kadm5
Binary files differ
diff --git a/third_party/heimdal/tests/kdc/hdb-mitdb.mkey b/third_party/heimdal/tests/kdc/hdb-mitdb.mkey
new file mode 100644
index 0000000..627c0fa
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/hdb-mitdb.mkey
Binary files differ
diff --git a/third_party/heimdal/tests/kdc/heimdal.acl b/third_party/heimdal/tests/kdc/heimdal.acl
new file mode 100644
index 0000000..2888a25
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/heimdal.acl
@@ -0,0 +1,10 @@
+foo/admin@TEST.H5L.SE all
+httpkadmind/admin@TEST.H5L.SE all,get-keys
+bar@TEST.H5L.SE all
+baz@TEST.H5L.SE get,add *
+bez@TEST.H5L.SE get,add *@TEST.H5L.SE
+fez@TEST.H5L.SE get,add
+hasalias@TEST.H5L.SE get,mod hasalias@TEST.H5L.SE
+hasalias@TEST.H5L.SE get,add goodalias1@TEST.H5L.SE
+hasalias@TEST.H5L.SE get,add goodalias2@TEST.H5L.SE
+hasalias@TEST.H5L.SE get,add goodalias3@TEST.H5L.SE
diff --git a/third_party/heimdal/tests/kdc/iprop-acl b/third_party/heimdal/tests/kdc/iprop-acl
new file mode 100644
index 0000000..334a407
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/iprop-acl
@@ -0,0 +1 @@
+iprop/slave.test.h5l.se@TEST.H5L.SE
diff --git a/third_party/heimdal/tests/kdc/k5login/foo b/third_party/heimdal/tests/kdc/k5login/foo
new file mode 100644
index 0000000..b51a40b
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/k5login/foo
@@ -0,0 +1 @@
+random-princ@RANDOM-REALM
diff --git a/third_party/heimdal/tests/kdc/k5login/mapped_user1 b/third_party/heimdal/tests/kdc/k5login/mapped_user1
new file mode 100644
index 0000000..a7857c2
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/k5login/mapped_user1
@@ -0,0 +1 @@
+user1@TEST.H5L.SE
diff --git a/third_party/heimdal/tests/kdc/kdc-tester1.json b/third_party/heimdal/tests/kdc/kdc-tester1.json
new file mode 100644
index 0000000..08a7744
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/kdc-tester1.json
@@ -0,0 +1,31 @@
+[
+ {
+ "op" : "repeat",
+ "num" : 333,
+ "value" : {
+ "op" : "kinit",
+ "client" : "foo@TEST.H5L.SE",
+ "password" : "foo"
+ }
+ },
+ {
+ "op" : "kinit",
+ "client" : "foo@TEST.H5L.SE",
+ "password" : "foo",
+ "ccache" : "MEMORY:cache"
+ },
+ {
+ "op" : "repeat",
+ "num" : 333,
+ "value" : {
+ "op" : "kgetcred",
+ "server" : "host/datan.test.h5l.se@TEST.H5L.SE",
+ "ccache" : "MEMORY:cache"
+ }
+ },
+ {
+ "op" : "kdestroy",
+ "ccache" : "MEMORY:cache"
+ }
+]
+
diff --git a/third_party/heimdal/tests/kdc/kdc-tester2.json b/third_party/heimdal/tests/kdc/kdc-tester2.json
new file mode 100644
index 0000000..207ae37
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/kdc-tester2.json
@@ -0,0 +1,12 @@
+[
+ {
+ "op" : "repeat",
+ "num" : 333,
+ "value" : {
+ "op" : "kinit",
+ "client" : "foo@TEST.H5L.SE",
+ "keytab" : "FILE:server.keytab"
+ }
+ }
+]
+
diff --git a/third_party/heimdal/tests/kdc/kdc-tester3.json b/third_party/heimdal/tests/kdc/kdc-tester3.json
new file mode 100644
index 0000000..682e485
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/kdc-tester3.json
@@ -0,0 +1,23 @@
+[
+ {
+ "op" : "kinit",
+ "client" : "host/datan.test.h5l.se@TEST.H5L.SE",
+ "keytab" : "FILE:server.keytab",
+ "ccache" : "MEMORY:fast-cc"
+ },
+ {
+ "op" : "repeat",
+ "num" : 333,
+ "value" : {
+ "op" : "kinit",
+ "client" : "foo@TEST.H5L.SE",
+ "keytab" : "FILE:server.keytab",
+ "fast-armor-cc" : "MEMORY:fast-cc"
+ }
+ },
+ {
+ "op" : "kdestroy",
+ "ccache" : "MEMORY:fast-cc"
+ }
+]
+
diff --git a/third_party/heimdal/tests/kdc/kdc-tester4.json.in b/third_party/heimdal/tests/kdc/kdc-tester4.json.in
new file mode 100644
index 0000000..0cbc337
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/kdc-tester4.json.in
@@ -0,0 +1,22 @@
+[
+ {
+ "op" : "repeat",
+ "num" : 333,
+ "value" : {
+ "op" : "kinit",
+ "client" : "foo@TEST.H5L.SE",
+ "pkinit-user-cert-id" : "FILE:@top_srcdir@/lib/hx509/data/pkinit.crt,@top_srcdir@/lib/hx509/data/pkinit.key"
+ }
+ },
+ {
+ "op" : "repeat",
+ "num" : 333,
+ "value" : {
+ "op" : "kinit",
+ "client" : "foo@TEST.H5L.SE",
+ "pkinit-user-cert-id" : "FILE:@top_srcdir@/lib/hx509/data/pkinit.crt,@top_srcdir@/lib/hx509/data/pkinit.key",
+ "pkinit-use-rsa" : true
+ }
+ }
+]
+
diff --git a/third_party/heimdal/tests/kdc/krb5-authz.conf.in b/third_party/heimdal/tests/kdc/krb5-authz.conf.in
new file mode 100644
index 0000000..0d4f38b
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-authz.conf.in
@@ -0,0 +1,26 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE TEST2.H5L.SE TEST3.H5L.SE
+ no-addresses = TRUE
+ kuserok = SYSTEM-K5LOGIN:@srcdir@/k5login
+ kuserok = USER-K5LOGIN
+ kuserok = SIMPLE
+
+[appdefaults]
+
+[realms]
+ TEST.H5L.SE = {
+ auth_to_local_names = {
+ foo/mapped1 = foo
+ foo/mapped2 = bar
+ mapped1 = foo
+ mapped2 = bar
+ }
+ auth_to_local = DB:@srcdir@/an2ln-db.txt DEFAULT
+ }
+
+[hdb]
+ db-dir = @objdir@
+
+[logging]
+ default = 0-/FILE:@objdir@/messages.log
+
diff --git a/third_party/heimdal/tests/kdc/krb5-authz2.conf.in b/third_party/heimdal/tests/kdc/krb5-authz2.conf.in
new file mode 100644
index 0000000..9a8efb0
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-authz2.conf.in
@@ -0,0 +1,27 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE TEST2.H5L.SE TEST3.H5L.SE
+ no-addresses = TRUE
+ k5login_authoritative = TRUE
+ k5login_directory = @srcdir@/k5login
+ kuserok = SYSTEM-K5LOGIN
+ kuserok = SIMPLE
+
+[appdefaults]
+
+[realms]
+ TEST.H5L.SE = {
+ auth_to_local_names = {
+ foo/mapped1 = foo
+ foo/mapped2 = bar
+ mapped1 = foo
+ mapped2 = bar
+ }
+ auth_to_local = DB:@srcdir@/an2ln-db.txt DEFAULT
+ }
+
+[hdb]
+ db-dir = @objdir@
+
+[logging]
+ default = 0-/FILE:@objdir@/messages.log
+
diff --git a/third_party/heimdal/tests/kdc/krb5-bx509.conf.in b/third_party/heimdal/tests/kdc/krb5-bx509.conf.in
new file mode 100644
index 0000000..2cd6fef
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-bx509.conf.in
@@ -0,0 +1,182 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE
+ no-addresses = TRUE
+ allow_weak_crypto = TRUE
+ rdns = false
+ fcache_strict_checking = false
+ name_canon_rules = as-is:realm=TEST.H5L.SE
+
+[appdefaults]
+ pkinit_anchors = FILE:@objdir@/pkinit-anchor.pem
+ pkinit_pool = FILE:@objdir@/pkinit-anchor.pem
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ pkinit_win2k = @w2k@
+ }
+
+[kdc]
+ check-ticket-addresses = no
+ warn_ticket_addresses = yes
+ num-kdc-processes = 1
+ strict-nametypes = true
+ enable-pkinit = true
+ pkinit_identity = PEM-FILE:@objdir@/user-issuer.pem
+ pkinit_anchors = PEM-FILE:@objdir@/pkinit-anchor.pem
+ pkinit_mappings_file = @srcdir@/pki-mapping
+
+ # Locate kdc plugins for testing
+ plugin_dir = @objdir@/../../kdc/.libs
+
+ enable-pkinit = true
+ pkinit_identity = PEM-FILE:@objdir@/user-issuer.pem
+ pkinit_anchors = PEM-FILE:@objdir@/pkinit-anchor.pem
+ pkinit_mappings_file = @srcdir@/pki-mapping
+ pkinit_max_life_from_cert = 5d
+
+ database = {
+ dbname = @objdir@/current-db
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ log_file = @objdir@/log.current-db.log
+ }
+
+ negotiate_token_validator = {
+ keytab = FILE:@objdir@/kt
+ }
+
+ realms = {
+ TEST.H5L.SE = {
+ kx509 = {
+ user = {
+ include_pkinit_san = true
+ subject_name = CN=${principal-name-without-realm},DC=test,DC=h5l,DC=se
+ ekus = 1.3.6.1.5.5.7.3.2
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ }
+ hostbased_service = {
+ HTTP = {
+ include_dnsname_san = true
+ ekus = 1.3.6.1.5.5.7.3.1
+ ca = PEM-FILE:@objdir@/server-issuer.pem
+ }
+ }
+ client = {
+ ekus = 1.3.6.1.5.5.7.3.2
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ }
+ server = {
+ ekus = 1.3.6.1.5.5.7.3.1
+ ca = PEM-FILE:@objdir@/server-issuer.pem
+ }
+ mixed = {
+ ekus = 1.3.6.1.5.5.7.3.1
+ ekus = 1.3.6.1.5.5.7.3.2
+ ca = PEM-FILE:@objdir@/mixed-issuer.pem
+ }
+ }
+ }
+ }
+
+[hdb]
+ db-dir = @objdir@
+
+[bx509]
+ realms = {
+ TEST.H5L.SE = {
+ # Default (no cert exts requested)
+ user = {
+ # Use an issuer for user certs:
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ subject_name = CN=${principal-name-without-realm},DC=test,DC=h5l,DC=se
+ ekus = 1.3.6.1.5.5.7.3.2
+ include_pkinit_san = true
+ }
+ hostbased_service = {
+ # Only for HTTP services
+ HTTP = {
+ # Use an issuer for server certs:
+ ca = PEM-FILE:@objdir@/server-issuer.pem
+ include_dnsname_san = true
+ # Don't bother with a template
+ }
+ }
+ # Non-default certs (extensions requested)
+ #
+ # Use no templates -- get empty subject names,
+ # use SANs.
+ #
+ # Use appropriate issuers.
+ client = {
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ }
+ server = {
+ ca = PEM-FILE:@objdir@/server-issuer.pem
+ }
+ mixed = {
+ ca = PEM-FILE:@objdir@/mixed-issuer.pem
+ }
+ }
+ }
+
+[get-tgt]
+ no_addresses = true
+ allow_addresses = true
+ realms = {
+ TEST.H5L.SE = {
+ # Default (no cert exts requested)
+ client = {
+ # Use an issuer for user certs:
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ subject_name = CN=${principal-name-without-realm},DC=test,DC=h5l,DC=se
+ ekus = 1.3.6.1.5.5.7.3.2
+ include_pkinit_san = true
+ allow_extra_lifetime = true
+ max_cert_lifetime = 7d
+ force_cert_lifetime = 2d
+ }
+ user = {
+ # Use an issuer for user certs:
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ subject_name = CN=${principal-name-without-realm},DC=test,DC=h5l,DC=se
+ ekus = 1.3.6.1.5.5.7.3.2
+ include_pkinit_san = true
+ allow_extra_lifetime = true
+ max_cert_lifetime = 7d
+ force_cert_lifetime = 2d
+ }
+ hostbased_service = {
+ # Only for HTTP services
+ HTTP = {
+ # Use an issuer for server certs:
+ ca = PEM-FILE:@objdir@/server-issuer.pem
+ include_dnsname_san = true
+ # Don't bother with a template
+ }
+ }
+ # Non-default certs (extensions requested)
+ #
+ # Use no templates -- get empty subject names,
+ # use SANs.
+ #
+ # Use appropriate issuers.
+ client = {
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ }
+ server = {
+ ca = PEM-FILE:@objdir@/server-issuer.pem
+ }
+ mixed = {
+ ca = PEM-FILE:@objdir@/mixed-issuer.pem
+ }
+ }
+ }
+
+[logging]
+ kdc = 0-/FILE:@objdir@/messages.log
+ bx509d = 0-/FILE:@objdir@/messages.log
+ default = 0-/FILE:@objdir@/messages.log
+
+[domain_realm]
+ . = TEST.H5L.SE
diff --git a/third_party/heimdal/tests/kdc/krb5-canon.conf.in b/third_party/heimdal/tests/kdc/krb5-canon.conf.in
new file mode 100644
index 0000000..0ce45b5
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-canon.conf.in
@@ -0,0 +1,100 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE TEST2.H5L.SE
+ no-addresses = TRUE
+ dns_lookup_realm = no
+ name_canon_rules = as-is:realm=TEST.H5L.SE
+ name_canon_rules = as-is:realm=TEST2.H5L.SE
+ name_canon_rules = as-is:realm=TEST3.H5L.SE
+ name_canon_rules = qualify:domain=test1.h5l.se:realm=TEST.H5L.SE
+ name_canon_rules = qualify:domain=test1.h5l.se:realm=TEST2.H5L.SE
+ name_canon_rules = qualify:domain=test2.h5l.se:realm=TEST2.H5L.SE
+ name_canon_rules = qualify:domain=test3.h5l.se:realm=TEST3.H5L.SE
+
+[appdefaults]
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ reconnect-min = 2s
+ reconnect-backoff = 2s
+ reconnect-max = 10s
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ admin_server = localhost:@admport@
+ kpasswd_server = localhost:@pwport@
+ }
+ TEST2.H5L.SE = {
+ kdc = localhost:@port@
+ kpasswd_server = localhost:@pwport@
+ }
+ TEST3.H5L.SE = {
+ kdc = localhost:@port@
+ }
+
+[domain_realm]
+ .test1.h5l.se = TEST.H5L.SE
+ .test2.h5l.se = TEST2.H5L.SE
+ .test3.h5l.se = TEST3.H5L.SE
+ localhost = TEST.H5L.SE
+
+
+[kdc]
+ enable-digest = true
+ allow-anonymous = true
+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+ strict-nametypes = true
+
+ enable-http = true
+
+ enable-pkinit = true
+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+ pkinit_mappings_file = @srcdir@/pki-mapping
+ pkinit_allow_proxy_certificate = true
+
+ database = {
+ label = {
+ dbname = @objdir@/current-db@kdc@
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ label2 = {
+ dbname = @objdir@/current-db@kdc@
+ realm = TEST2.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ }
+
+ signal_socket = @objdir@/signal
+ iprop-stats = @objdir@/iprop-stats
+ iprop-acl = @srcdir@/iprop-acl
+
+[hdb]
+ db-dir = @objdir@
+
+[logging]
+ kdc = 0-/FILE:@objdir@/messages.log
+ default = 0-/FILE:@objdir@/messages.log
+
+[kadmin]
+ save-password = true
+ @dk@
+
+[capaths]
+ TEST.H5L.SE = {
+ TEST3.H5L.SE = .
+ TEST2.H5L.SE = .
+ }
+ TEST2.H5L.SE = {
+ TEST.H5L.SE = .
+ TEST3.H5L.SE = .
+ }
+ TEST3.H5L.SE = {
+ TEST.H5L.SE = .
+ TEST2.H5L.SE = .
+ }
diff --git a/third_party/heimdal/tests/kdc/krb5-canon2.conf.in b/third_party/heimdal/tests/kdc/krb5-canon2.conf.in
new file mode 100644
index 0000000..dae71d3
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-canon2.conf.in
@@ -0,0 +1,97 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE TEST2.H5L.SE
+ no-addresses = TRUE
+ dns_lookup_realm = no
+ name_canon_rules = as-is:realm=TEST.H5L.SE
+ name_canon_rules = as-is:realm=TEST2.H5L.SE
+ name_canon_rules = as-is:realm=TEST3.H5L.SE
+ name_canon_rules = nss
+
+[appdefaults]
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ reconnect-min = 2s
+ reconnect-backoff = 2s
+ reconnect-max = 10s
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ admin_server = localhost:@admport@
+ kpasswd_server = localhost:@pwport@
+ }
+ TEST2.H5L.SE = {
+ kdc = localhost:@port@
+ kpasswd_server = localhost:@pwport@
+ }
+ TEST3.H5L.SE = {
+ kdc = localhost:@port@
+ }
+
+[domain_realm]
+ .test1.h5l.se = TEST.H5L.SE
+ .test2.h5l.se = TEST2.H5L.SE
+ .test3.h5l.se = TEST3.H5L.SE
+ localhost = TEST.H5L.SE
+
+
+[kdc]
+ enable-digest = true
+ allow-anonymous = true
+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+ strict-nametypes = true
+
+ enable-http = true
+
+ enable-pkinit = true
+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+ pkinit_mappings_file = @srcdir@/pki-mapping
+ pkinit_allow_proxy_certificate = true
+
+ database = {
+ label = {
+ dbname = @objdir@/current-db@kdc@
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ label2 = {
+ dbname = @objdir@/current-db@kdc@
+ realm = TEST2.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ }
+
+ signal_socket = @objdir@/signal
+ iprop-stats = @objdir@/iprop-stats
+ iprop-acl = @srcdir@/iprop-acl
+
+[hdb]
+ db-dir = @objdir@
+
+[logging]
+ kdc = 0-/FILE:@objdir@/messages.log
+ default = 0-/FILE:@objdir@/messages.log
+
+[kadmin]
+ save-password = true
+ @dk@
+
+[capaths]
+ TEST.H5L.SE = {
+ TEST3.H5L.SE = .
+ TEST2.H5L.SE = .
+ }
+ TEST2.H5L.SE = {
+ TEST.H5L.SE = .
+ TEST3.H5L.SE = .
+ }
+ TEST3.H5L.SE = {
+ TEST.H5L.SE = .
+ TEST2.H5L.SE = .
+ }
diff --git a/third_party/heimdal/tests/kdc/krb5-cccol.conf.in b/third_party/heimdal/tests/kdc/krb5-cccol.conf.in
new file mode 100644
index 0000000..819de80
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-cccol.conf.in
@@ -0,0 +1,165 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE TEST2.H5L.SE
+ default_cc_collection = DIR:@objdir@/cc_dir/
+ no-addresses = TRUE
+ allow_weak_crypto = @WEAK@
+ dns_lookup_kdc = no
+ dns_lookup_realm = no
+
+
+[appdefaults]
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ reconnect-min = 2s
+ reconnect-backoff = 2s
+ reconnect-max = 10s
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ admin_server = localhost:@admport@
+ kpasswd_server = localhost:@pwport@
+ }
+ SUB.TEST.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ TEST2.H5L.SE = {
+ kdc = localhost:@port@
+ kpasswd_server = localhost:@pwport@
+ }
+ TEST3.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ TEST4.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM5.FR = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM6.US = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM7.UK = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM8.UK = {
+ kdc = localhost:@port@
+ }
+ 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
+ localdomain = TEST.H5L.SE
+ .localdomain6 = TEST.H5L.SE
+ localdomain6 = TEST.H5L.SE
+
+
+[kdc]
+ enable-digest = true
+ allow-anonymous = true
+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+ strict-nametypes = true
+
+ enable-http = true
+
+ enable-pkinit = true
+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+ pkinit_mappings_file = @srcdir@/pki-mapping
+ pkinit_allow_proxy_certificate = true
+
+ database = {
+ label = {
+ dbname = @db_type@:@objdir@/current-db@kdc@
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ label2 = {
+ dbname = @db_type@:@objdir@/current-db@kdc@
+ realm = TEST2.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ label3 = {
+ dbname = sqlite:@objdir@/current-db@kdc@.sqlite3
+ realm = SOME-REALM5.FR
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ }
+
+ signal_socket = @objdir@/signal
+ iprop-stats = @objdir@/iprop-stats
+ iprop-acl = @srcdir@/iprop-acl
+ log-max-size = 40000
+
+[hdb]
+ db-dir = @objdir@
+
+[logging]
+ kdc = 0-/FILE:@objdir@/messages.log
+ krb5 = 0-/FILE:@objdir@/messages.log
+ default = 0-/FILE:@objdir@/messages.log
+
+# If you are doing preformance measurements on OSX you want to change
+# the kdc LOG line from = to - below to keep the FILE open and avoid
+# open/write/close which is blocking (rdar:// ) on OSX.
+# kdc = 0-/FILE=@objdir@/messages.log
+
+[kadmin]
+ save-password = true
+ default_key_rules = {
+ */des3-only@* = des3-cbc-sha1:pw-salt
+ */aes-only@* = aes256-cts-hmac-sha1-96:pw-salt
+ }
+ @dk@
+
+[capaths]
+ TEST.H5L.SE = {
+ TEST2.H5L.SE = .
+ SOME-REALM5.FR = 1
+ TEST3.H5L.SE = TEST2.H5L.SE
+ TEST4.H5L.SE = TEST2.H5L.SE
+ TEST4.H5L.SE = TEST3.H5L.SE
+ SOME-REALM6.US = SOME-REALM5.FR
+ SOME-REALM7.UK = SOME-REALM6.US
+ SOME-REALM7.UK = SOME-REALM5.FR
+ SOME-REALM8.UK = SOME-REALM6.US
+ }
+ 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
+ }
diff --git a/third_party/heimdal/tests/kdc/krb5-hdb-mitdb.conf.in b/third_party/heimdal/tests/kdc/krb5-hdb-mitdb.conf.in
new file mode 100644
index 0000000..2be7eed
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-hdb-mitdb.conf.in
@@ -0,0 +1,60 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE TEST2.H5L.SE
+ no-addresses = TRUE
+ allow_weak_crypto = TRUE
+
+[appdefaults]
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ reconnect-min = 2s
+ reconnect-backoff = 2s
+ reconnect-max = 10s
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ admin_server = localhost:@admport@
+ kpasswd_server = localhost:@pwport@
+ }
+
+[domain_realm]
+ .test.h5l.se = TEST.H5L.SE
+ localhost = TEST.H5L.SE
+
+[kdc]
+ enable-digest = true
+ allow-anonymous = true
+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+ strict-nametypes = true
+
+ enable-http = true
+
+ enable-pkinit = true
+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+ pkinit_mappings_file = @srcdir@/pki-mapping
+ pkinit_allow_proxy_certificate = true
+
+ database = {
+ label = {
+ dbname = mit-db:@srcdir@/hdb-mitdb
+ realm = TEST.H5L.SE
+ mkey_file = @srcdir@/hdb-mitdb.mkey
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ }
+
+ signal_socket = @objdir@/signal
+ iprop-stats = @objdir@/iprop-stats
+ iprop-acl = @srcdir@/iprop-acl
+
+[logging]
+ kdc = 0-/FILE:@objdir@/messages.log
+ default = 0-/FILE:@objdir@/messages.log
+
+[kadmin]
+ save-password = true
+ @dk@
+
diff --git a/third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in b/third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in
new file mode 100644
index 0000000..fb2fc6a
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in
@@ -0,0 +1,98 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE
+ no-addresses = TRUE
+ allow_weak_crypto = TRUE
+ rdns = false
+ fcache_strict_checking = false
+ name_canon_rules = as-is:realm=TEST.H5L.SE
+
+[appdefaults]
+ pkinit_anchors = FILE:@objdir@/ca.crt
+ pkinit_pool = FILE:@objdir@/ca.crt
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ pkinit_win2k = @w2k@
+ }
+
+[kdc]
+ num-kdc-processes = 1
+ strict-nametypes = true
+ synthetic_clients = true
+ enable-pkinit = true
+ pkinit_identity = FILE:@objdir@/kdc.crt,@srcdir@/../../lib/hx509/data/key2.der
+ pkinit_anchors = FILE:@objdir@/ca.crt
+ pkinit_mappings_file = @srcdir@/pki-mapping
+
+ # Locate kdc plugins for testing
+ plugin_dir = @objdir@/../../kdc/.libs
+
+ database = {
+ dbname = @objdir@/current-db
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ log_file = @objdir@/log.current-db.log
+ acl_file = @srcdir@/heimdal.acl
+ }
+
+ negotiate_token_validator = {
+ keytab = FILE:@objdir@/kt
+ }
+
+ realms = {
+ TEST.H5L.SE = {
+ kx509 = {
+ user = {
+ include_pkinit_san = true
+ subject_name = CN=${principal-name-without-realm},DC=test,DC=h5l,DC=se
+ ekus = 1.3.6.1.5.5.7.3.2
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ }
+ hostbased_service = {
+ HTTP = {
+ include_dnsname_san = true
+ ekus = 1.3.6.1.5.5.7.3.1
+ ca = PEM-FILE:@objdir@/server-issuer.pem
+ }
+ }
+ client = {
+ ekus = 1.3.6.1.5.5.7.3.2
+ ca = PEM-FILE:@objdir@/user-issuer.pem
+ }
+ server = {
+ ekus = 1.3.6.1.5.5.7.3.1
+ ca = PEM-FILE:@objdir@/server-issuer.pem
+ }
+ mixed = {
+ ekus = 1.3.6.1.5.5.7.3.1
+ ekus = 1.3.6.1.5.5.7.3.2
+ ca = PEM-FILE:@objdir@/mixed-issuer.pem
+ }
+ }
+ }
+ }
+
+[hdb]
+ db-dir = @objdir@
+ enable_virtual_hostbased_princs = true
+ virtual_hostbased_princ_mindots = 1
+ virtual_hostbased_princ_maxdots = 3
+ virtual_hostbased_princ_svcs = HTTP host
+
+[ext_keytab]
+ new_hostbased_service_principal_attributes = {
+ host = {
+ a-particular-hostname.test.h5l.se = ok-as-delegate,no-auth-data-reqd
+ .prod.test.h5l.se = ok-as-delegate no-auth-data-reqd
+ }
+ }
+
+[logging]
+ kdc = 0-/FILE:@objdir@/messages.log
+ bx509d = 0-/FILE:@objdir@/messages.log
+ httpkadmind = 0-/FILE:@objdir@/messages.log
+ default = 0-/FILE:@objdir@/messages.log
+
+[domain_realm]
+ . = TEST.H5L.SE
diff --git a/third_party/heimdal/tests/kdc/krb5-kcm.conf.in b/third_party/heimdal/tests/kdc/krb5-kcm.conf.in
new file mode 100644
index 0000000..bdcca07
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-kcm.conf.in
@@ -0,0 +1,165 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE TEST2.H5L.SE
+ default_ccache_name = KCM:%{uid}
+ no-addresses = TRUE
+ allow_weak_crypto = @WEAK@
+ dns_lookup_kdc = no
+ dns_lookup_realm = no
+
+
+[appdefaults]
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ reconnect-min = 2s
+ reconnect-backoff = 2s
+ reconnect-max = 10s
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ admin_server = localhost:@admport@
+ kpasswd_server = localhost:@pwport@
+ }
+ SUB.TEST.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ TEST2.H5L.SE = {
+ kdc = localhost:@port@
+ kpasswd_server = localhost:@pwport@
+ }
+ TEST3.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ TEST4.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM5.FR = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM6.US = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM7.UK = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM8.UK = {
+ kdc = localhost:@port@
+ }
+ 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
+ localdomain = TEST.H5L.SE
+ .localdomain6 = TEST.H5L.SE
+ localdomain6 = TEST.H5L.SE
+
+
+[kdc]
+ enable-digest = true
+ allow-anonymous = true
+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+ strict-nametypes = true
+
+ enable-http = true
+
+ enable-pkinit = true
+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+ pkinit_mappings_file = @srcdir@/pki-mapping
+ pkinit_allow_proxy_certificate = true
+
+ database = {
+ label = {
+ dbname = @db_type@:@objdir@/current-db@kdc@
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ label2 = {
+ dbname = @db_type@:@objdir@/current-db@kdc@
+ realm = TEST2.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ label3 = {
+ dbname = sqlite:@objdir@/current-db@kdc@.sqlite3
+ realm = SOME-REALM5.FR
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ }
+
+ signal_socket = @objdir@/signal
+ iprop-stats = @objdir@/iprop-stats
+ iprop-acl = @srcdir@/iprop-acl
+ log-max-size = 40000
+
+[hdb]
+ db-dir = @objdir@
+
+[logging]
+ kdc = 0-/FILE:@objdir@/messages.log
+ krb5 = 0-/FILE:@objdir@/messages.log
+ default = 0-/FILE:@objdir@/messages.log
+
+# If you are doing preformance measurements on OSX you want to change
+# the kdc LOG line from = to - below to keep the FILE open and avoid
+# open/write/close which is blocking (rdar:// ) on OSX.
+# kdc = 0-/FILE=@objdir@/messages.log
+
+[kadmin]
+ save-password = true
+ default_key_rules = {
+ */des3-only@* = des3-cbc-sha1:pw-salt
+ */aes-only@* = aes256-cts-hmac-sha1-96:pw-salt
+ }
+ @dk@
+
+[capaths]
+ TEST.H5L.SE = {
+ TEST2.H5L.SE = .
+ SOME-REALM5.FR = 1
+ TEST3.H5L.SE = TEST2.H5L.SE
+ TEST4.H5L.SE = TEST2.H5L.SE
+ TEST4.H5L.SE = TEST3.H5L.SE
+ SOME-REALM6.US = SOME-REALM5.FR
+ SOME-REALM7.UK = SOME-REALM6.US
+ SOME-REALM7.UK = SOME-REALM5.FR
+ SOME-REALM8.UK = SOME-REALM6.US
+ }
+ 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
+ }
diff --git a/third_party/heimdal/tests/kdc/krb5-pkinit.conf.in b/third_party/heimdal/tests/kdc/krb5-pkinit.conf.in
new file mode 100644
index 0000000..e2d3f3d
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-pkinit.conf.in
@@ -0,0 +1,82 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE
+ no-addresses = TRUE
+ allow_weak_crypto = TRUE
+ enable_kx509 = true
+
+[appdefaults]
+ pkinit_anchors = FILE:@objdir@/ca.crt
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ pkinit_win2k = @w2k@
+ }
+
+[kdc]
+ strict-nametypes = true
+ synthetic_clients = true
+ enable-pkinit = true
+ pkinit_identity = FILE:@objdir@/kdc.crt,@srcdir@/../../lib/hx509/data/key2.der
+ pkinit_anchors = FILE:@objdir@/ca.crt
+ pkinit_mappings_file = @srcdir@/pki-mapping
+ pkinit_max_life_from_cert_extension = true
+ pkinit_max_life_from_cert = @max_life_from_cert@
+
+ plugin_dir = @objdir@/../../kdc/.libs
+
+ ipc_csr_authorizer = {
+ optional = true
+ }
+
+ enable_kx509 = true
+ require_initial_kca_tickets = false
+
+ database = {
+ dbname = @objdir@/current-db
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ log_file = @objdir@/log.current-db.log
+ }
+
+
+ realms = {
+ TEST.H5L.SE = {
+ negotiate_token_validator = {
+ keytab = HDBGET:@objdir@/current-db
+ }
+ kx509 = {
+ user = {
+ include_pkinit_san = true
+ subject_name = CN=${principal-name-without-realm},DC=TEST,DC=H5L,DC=SE
+ ekus = 1.3.6.1.5.5.7.3.2
+ ca = FILE:@objdir@/ca.crt,@srcdir@/../../lib/hx509/data/key.der
+ template_cert = FILE:@objdir@/kx509-template.crt
+ }
+ hostbased_service = {
+ HTTP = {
+ include_dnsname_san = true
+ ekus = 1.3.6.1.5.5.7.3.1
+ ca = FILE:@objdir@/ca.crt,@srcdir@/../../lib/hx509/data/key.der
+ }
+ }
+ client = {
+ ca = FILE:@objdir@/ca.crt,@srcdir@/../../lib/hx509/data/key.der
+ }
+ server = {
+ ekus = 1.3.6.1.5.5.7.3.1
+ ca = FILE:@objdir@/ca.crt,@srcdir@/../../lib/hx509/data/key.der
+ }
+ }
+ }
+ }
+
+[hdb]
+ db-dir = @objdir@
+
+[logging]
+ kdc = 0-/FILE:@objdir@/messages.log
+ default = 0-/FILE:@objdir@/messages.log
+
+[kadmin]
+ save-password = true
diff --git a/third_party/heimdal/tests/kdc/krb5.conf.in b/third_party/heimdal/tests/kdc/krb5.conf.in
new file mode 100644
index 0000000..5b9d644
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5.conf.in
@@ -0,0 +1,175 @@
+[libdefaults]
+ default_realm = TEST.H5L.SE TEST2.H5L.SE
+ no-addresses = TRUE
+ allow_weak_crypto = @WEAK@
+ dns_lookup_kdc = no
+ dns_lookup_realm = no
+
+
+[appdefaults]
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ reconnect-min = 2s
+ reconnect-backoff = 2s
+ reconnect-max = 10s
+
+[realms]
+ TEST.H5L.SE = {
+ kdc = localhost:@port@
+ admin_server = localhost:@admport@
+ kpasswd_server = localhost:@pwport@
+ }
+ SUB.TEST.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ TEST2.H5L.SE = {
+ kdc = localhost:@port@
+ kpasswd_server = localhost:@pwport@
+ }
+ TEST3.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ TEST4.H5L.SE = {
+ kdc = localhost:@port@
+ }
+ XTST.HEIM.EXAMPLE = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM5.FR = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM6.US = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM7.UK = {
+ kdc = localhost:@port@
+ }
+ SOME-REALM8.UK = {
+ kdc = localhost:@port@
+ }
+ 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
+ localdomain = TEST.H5L.SE
+ .localdomain6 = TEST.H5L.SE
+ localdomain6 = TEST.H5L.SE
+
+
+[kdc]
+ enable-digest = true
+ allow-anonymous = true
+ digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+ strict-nametypes = true
+
+ enable-http = true
+
+ synthetic_clients = true
+
+ enable_gss_preauth = true
+ gss_mechanisms_allowed = sanon-x25519
+
+ enable-pkinit = true
+ pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+ pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+ pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+# pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+ pkinit_mappings_file = @srcdir@/pki-mapping
+ pkinit_allow_proxy_certificate = true
+
+ database = {
+ label = {
+ dbname = @db_type@:@objdir@/current-db@kdc@
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ label2 = {
+ dbname = @db_type@:@objdir@/current-db@kdc@
+ realm = TEST2.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ label3 = {
+ dbname = sqlite:@objdir@/current-db@kdc@.sqlite3
+ realm = SOME-REALM5.FR
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/current@kdc@.log
+ }
+ }
+
+ signal_socket = @objdir@/@signalsocket@
+ iprop-stats = @objdir@/@ipropstats@
+ iprop-acl = @srcdir@/iprop-acl
+ log-max-size = 40000
+
+[hdb]
+ db-dir = @objdir@
+ enable_virtual_hostbased_princs = true
+ virtual_hostbased_princ_mindots = 1
+ virtual_hostbased_princ_maxdots = 3
+
+[logging]
+ kdc = 0-/FILE:@objdir@/@messages@.log
+ krb5 = 0-/FILE:@objdir@/@messages@.log
+ default = 0-/FILE:@objdir@/@messages@.log
+
+# If you are doing preformance measurements on OSX you want to change
+# the kdc LOG line from = to - below to keep the FILE open and avoid
+# open/write/close which is blocking (rdar:// ) on OSX.
+# kdc = 0-/FILE=@objdir@/@messages@.log
+
+[kadmin]
+ save-password = true
+ default_key_rules = {
+ */des3-only@* = des3-cbc-sha1:pw-salt
+ */aes-only@* = aes256-cts-hmac-sha1-96:pw-salt
+ }
+ @dk@
+
+[capaths]
+ TEST.H5L.SE = {
+ TEST2.H5L.SE = .
+ SOME-REALM5.FR = 1
+ TEST3.H5L.SE = TEST2.H5L.SE
+ TEST4.H5L.SE = TEST2.H5L.SE
+ TEST4.H5L.SE = TEST3.H5L.SE
+ SOME-REALM6.US = SOME-REALM5.FR
+ SOME-REALM7.UK = SOME-REALM6.US
+ SOME-REALM7.UK = SOME-REALM5.FR
+ SOME-REALM8.UK = SOME-REALM6.US
+ }
+ 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
+ }
diff --git a/third_party/heimdal/tests/kdc/krb5.conf.keys.in b/third_party/heimdal/tests/kdc/krb5.conf.keys.in
new file mode 100644
index 0000000..16891de
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5.conf.keys.in
@@ -0,0 +1,19 @@
+[libdefaults]
+ allow_weak_crypto = TRUE
+
+[kdc]
+ strict-nametypes = true
+ database = {
+ dbname = @objdir@/current-db
+ realm = TEST.H5L.SE
+ mkey_file = @objdir@/mkey.file
+ acl_file = @srcdir@/heimdal.acl
+ log_file = @objdir@/log.current-db.log
+ }
+
+[hdb]
+ db-dir = @objdir@
+
+
+[kadmin]
+ default_keys = @keys@
diff --git a/third_party/heimdal/tests/kdc/leaks-kill.sh b/third_party/heimdal/tests/kdc/leaks-kill.sh
new file mode 100644
index 0000000..1474bdd
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/leaks-kill.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+name=$1
+pid=$2
+
+kill $pid
+set -- .
+while kill -0 $pid 2>/dev/null
+do
+ set -- "$@" "."
+ if [ $# -gt 4 ]
+ then
+ kill kill -9 $pid 2> /dev/null
+ break
+ fi
+ sleep 1
+done
+
+set -- .
+while kill -0 $pid 2>/dev/null
+do
+ set -- "$@" "."
+ if [ $# -gt 4 ]; then exit 1; fi
+ sleep 1
+done
+
+exit 0
diff --git a/third_party/heimdal/tests/kdc/ntlm-user-file.txt b/third_party/heimdal/tests/kdc/ntlm-user-file.txt
new file mode 100644
index 0000000..d807127
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/ntlm-user-file.txt
@@ -0,0 +1 @@
+TEST:foo:digestpassword
diff --git a/third_party/heimdal/tests/kdc/pki-mapping b/third_party/heimdal/tests/kdc/pki-mapping
new file mode 100644
index 0000000..18fb481
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/pki-mapping
@@ -0,0 +1,2 @@
+foo@TEST.H5L.SE:CN=pkinit,C=SE
+foo@TEST.H5L.SE:CN=bar,DC=test,DC=h5l,DC=se
diff --git a/third_party/heimdal/tests/kdc/uuserver.txt b/third_party/heimdal/tests/kdc/uuserver.txt
new file mode 100644
index 0000000..2c191bf
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/uuserver.txt
@@ -0,0 +1,4 @@
+User is `user2@TEST.H5L.SE'
+Server is `user1@TEST.H5L.SE'
+safe packet: hej
+priv packet: hemligt
diff --git a/third_party/heimdal/tests/kdc/wait-kdc.sh b/third_party/heimdal/tests/kdc/wait-kdc.sh
new file mode 100644
index 0000000..d0226fc
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/wait-kdc.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+# (Royal Institute of Technology, Stockholm, Sweden).
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the Institute nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+name=${1:-KDC}
+log=${2:-messages.log}
+waitfor="${3:-${name} started}"
+
+t=0
+waitsec=65
+
+echo "Waiting for ${name} to start, see logfile ${log}"
+
+while true ; do
+ if grep "${waitfor}" ${log} > /dev/null; then
+ break
+ fi
+ if grep "No sockets" ${log} ; then
+ echo "The ${name} failed to bind to any sockets, another ${name} running ?"
+ exit 1
+ fi
+ if grep "bind" ${log} | grep "Operation not permitted" ; then
+ echo "The ${name} failed to bind to any sockets, another ${name} running ?"
+ exit 1
+ fi
+ if [ "$t" -gt $waitsec ]; then
+ echo "Error: ${name} failed to start after $waitsec seconds"
+ exit 2
+ fi
+
+ t=`expr ${t} + 2`
+ sleep 2
+ echo "Have waited $t seconds"
+done
+
+exit 0