From 4df0096f2013dc5bc9fad459ddc18e83ac4da4c2 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Wed, 9 Jun 2021 10:55:13 -0400 Subject: [PATCH] Fix three canonicalization cases for fallback --- ...ith-keytab-to-defer-canonicalization.patch | 60 + ...in-k-with-fallback-or-referral-realm.patch | 64 + ...incipal-realm-canonicalization-cases.patch | 96 + ...dejagnu-kadmin-tests-to-Python-tests.patch | 1750 +++++++++++++++++ krb5.spec | 9 +- 5 files changed, 1978 insertions(+), 1 deletion(-) create mode 100644 Allow-kinit-with-keytab-to-defer-canonicalization.patch create mode 100644 Fix-kadmin-k-with-fallback-or-referral-realm.patch create mode 100644 Fix-some-principal-realm-canonicalization-cases.patch create mode 100644 Move-some-dejagnu-kadmin-tests-to-Python-tests.patch diff --git a/Allow-kinit-with-keytab-to-defer-canonicalization.patch b/Allow-kinit-with-keytab-to-defer-canonicalization.patch new file mode 100644 index 0000000..9315f66 --- /dev/null +++ b/Allow-kinit-with-keytab-to-defer-canonicalization.patch @@ -0,0 +1,60 @@ +From 090c7319652466339e3e6482bdd1b5a294638dff Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 3 Jun 2021 16:03:07 -0400 +Subject: [PATCH] Allow kinit with keytab to defer canonicalization + +[ghudson@mit.edu: added tests] + +ticket: 9012 (new) +(cherry picked from commit 5e6a6efc5df689d9fb8730d0227167ffbb6ece0e) +--- + src/clients/kinit/kinit.c | 11 ----------- + src/tests/t_keytab.py | 13 +++++++++++++ + 2 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c +index d1f5d74c3..5a6d7237c 100644 +--- a/src/clients/kinit/kinit.c ++++ b/src/clients/kinit/kinit.c +@@ -510,17 +510,6 @@ k5_begin(struct k_opts *opts, struct k5_data *k5) + _("when creating default server principal name")); + goto cleanup; + } +- if (k5->me->realm.data[0] == 0) { +- ret = krb5_unparse_name(k5->ctx, k5->me, &k5->name); +- if (ret == 0) { +- com_err(progname, KRB5_ERR_HOST_REALM_UNKNOWN, +- _("(principal %s)"), k5->name); +- } else { +- com_err(progname, KRB5_ERR_HOST_REALM_UNKNOWN, +- _("for local services")); +- } +- goto cleanup; +- } + } else if (k5->out_cc != NULL) { + /* If the output ccache is initialized, use its principal. */ + if (krb5_cc_get_principal(k5->ctx, k5->out_cc, &princ) == 0) +diff --git a/src/tests/t_keytab.py b/src/tests/t_keytab.py +index 850375c92..a9adebb26 100755 +--- a/src/tests/t_keytab.py ++++ b/src/tests/t_keytab.py +@@ -41,6 +41,19 @@ realm.kinit(realm.user_princ, flags=['-i'], + expected_msg='keytab specified, forcing -k') + realm.klist(realm.user_princ) + ++# Test default principal for -k. This operation requires ++# canonicalization against the keytab in krb5_get_init_creds_keytab() ++# as the krb5_sname_to_principal() result won't have a realm. Try ++# with and without without fallback processing since the code paths ++# are different. ++mark('default principal for -k') ++realm.run([kinit, '-k']) ++realm.klist(realm.host_princ) ++no_canon_conf = {'libdefaults': {'dns_canonicalize_hostname': 'false'}} ++no_canon = realm.special_env('no_canon', False, krb5_conf=no_canon_conf) ++realm.run([kinit, '-k'], env=no_canon) ++realm.klist(realm.host_princ) ++ + # Test extracting keys with multiple key versions present. + mark('multi-kvno extract') + os.remove(realm.keytab) diff --git a/Fix-kadmin-k-with-fallback-or-referral-realm.patch b/Fix-kadmin-k-with-fallback-or-referral-realm.patch new file mode 100644 index 0000000..3e03da1 --- /dev/null +++ b/Fix-kadmin-k-with-fallback-or-referral-realm.patch @@ -0,0 +1,64 @@ +From cd8ff035f5b4720a8fc457355726f7bd0eab5eaa Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 7 Jun 2021 15:00:41 -0400 +Subject: [PATCH] Fix kadmin -k with fallback or referral realm + +kadmin -k produces a client principal name with +krb5_sname_to_principal(), but it gets converted to a string and back +due to the signature of kadm5_init_with_skey(), which loses track of +the name type, so no canonicalization is performed. + +In libkadm5clnt initialization, recognize the important subset of this +case--an empty realm indicates either fallback processing or the +referral realm--and restore the host-based name type so that the +client principal can be canonicalized against the keytab. + +ticket: 9013 (new) +(cherry picked from commit dcb79089276624d7ddf44e08d35bd6d7d7e557d2) +--- + src/lib/kadm5/clnt/client_init.c | 7 +++++++ + src/tests/t_kadmin.py | 12 ++++++++++++ + 2 files changed, 19 insertions(+) + +diff --git a/src/lib/kadm5/clnt/client_init.c b/src/lib/kadm5/clnt/client_init.c +index aa1223bb3..0aaca701f 100644 +--- a/src/lib/kadm5/clnt/client_init.c ++++ b/src/lib/kadm5/clnt/client_init.c +@@ -221,9 +221,16 @@ init_any(krb5_context context, char *client_name, enum init_type init_type, + return KADM5_MISSING_KRB5_CONF_PARAMS; + } + ++ /* ++ * Parse the client name. If it has an empty realm, it is almost certainly ++ * a host-based principal using DNS fallback processing or the referral ++ * realm, so give it the appropriate name type for canonicalization. ++ */ + code = krb5_parse_name(handle->context, client_name, &client); + if (code) + goto error; ++ if (init_type == INIT_SKEY && client->realm.length == 0) ++ client->type = KRB5_NT_SRV_HST; + + /* + * Get credentials. Also does some fallbacks in case kadmin/fqdn +diff --git a/src/tests/t_kadmin.py b/src/tests/t_kadmin.py +index fe6a3cc2e..98453d92e 100644 +--- a/src/tests/t_kadmin.py ++++ b/src/tests/t_kadmin.py +@@ -51,4 +51,16 @@ for i in range(200): + realm.run_kadmin(['addprinc', '-randkey', 'foo%d' % i]) + realm.run_kadmin(['listprincs'], expected_msg='foo199') + ++# Test kadmin -k with the default principal, with and without ++# fallback. This operation requires canonicalization against the ++# keytab in krb5_get_init_creds_keytab() as the ++# krb5_sname_to_principal() result won't have a realm. Try with and ++# without without fallback processing since the code paths are ++# different. ++mark('kadmin -k') ++realm.run([kadmin, '-k', 'getprinc', realm.host_princ]) ++no_canon_conf = {'libdefaults': {'dns_canonicalize_hostname': 'false'}} ++no_canon = realm.special_env('no_canon', False, krb5_conf=no_canon_conf) ++realm.run([kadmin, '-k', 'getprinc', realm.host_princ], env=no_canon) ++ + success('kadmin and kpasswd tests') diff --git a/Fix-some-principal-realm-canonicalization-cases.patch b/Fix-some-principal-realm-canonicalization-cases.patch new file mode 100644 index 0000000..2c6c915 --- /dev/null +++ b/Fix-some-principal-realm-canonicalization-cases.patch @@ -0,0 +1,96 @@ +From 5ae9bc98f23aeaa2ce17debe5a9b0cf1130e54ed Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 7 Jun 2021 13:27:29 -0400 +Subject: [PATCH] Fix some principal realm canonicalization cases + +The no_hostrealm and subst_defrealm flags in struct canonprinc were +only applied when dns_canonicalize_hostname=fallback; in the other +cases, the initial krb5_sname_to_principal() result is treated as +canonical. For no_hostrealm this limitation doesn't currently matter, +because all uses pass a principal with no realm as input. However, +subst_defrealm is used to convert the referral realm to the default +realm in krb5_get_init_creds_keytab(), krb5_cc_cache_match(), and +gss_acquire_cred() when it needs to check the desired name against a +specified ccache. + +In k5_canonprinc(), if the input principal is a +krb5_sname_to_principal() result and fallback isn't in effect, apply +subst_defrealm. Document in os-proto.h that no_hostrealm doesn't +remove an existing realm and that krb5_sname_to_principal() may +already have looked one up. + +ticket: 9011 (new) +(cherry picked from commit c077d0c6430c4ac163443aacc03d14d206a4cbb8) +--- + src/lib/krb5/os/os-proto.h | 13 +++++++++---- + src/lib/krb5/os/sn2princ.c | 24 +++++++++++++++++++++--- + 2 files changed, 30 insertions(+), 7 deletions(-) + +diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h +index 7d5e7978f..a985f2aec 100644 +--- a/src/lib/krb5/os/os-proto.h ++++ b/src/lib/krb5/os/os-proto.h +@@ -85,10 +85,15 @@ struct sendto_callback_info { + + /* + * Initialize with all zeros except for princ. Set no_hostrealm to disable +- * host-to-realm lookup, which ordinarily happens after canonicalizing the host +- * part. Set subst_defrealm to substitute the default realm for the referral +- * realm after realm lookup (this has no effect if no_hostrealm is set). Free +- * with free_canonprinc() when done. ++ * host-to-realm lookup, which ordinarily happens during fallback processing ++ * after canonicalizing the host part. Set subst_defrealm to substitute the ++ * default realm for the referral realm after realm lookup. Do not set both ++ * flags. Free with free_canonprinc() when done. ++ * ++ * no_hostrealm only applies if fallback processing is in use ++ * (dns_canonicalize_hostname = fallback). It will not remove the realm if ++ * krb5_sname_to_principal() already canonicalized the hostname and looked up a ++ * realm. subst_defrealm applies whether or not fallback processing is in use. + */ + struct canonprinc { + krb5_const_principal princ; +diff --git a/src/lib/krb5/os/sn2princ.c b/src/lib/krb5/os/sn2princ.c +index c99b7da17..93c155932 100644 +--- a/src/lib/krb5/os/sn2princ.c ++++ b/src/lib/krb5/os/sn2princ.c +@@ -271,18 +271,36 @@ krb5_error_code + k5_canonprinc(krb5_context context, struct canonprinc *iter, + krb5_const_principal *princ_out) + { ++ krb5_error_code ret; + int step = ++iter->step; + + *princ_out = NULL; + +- /* If we're not doing fallback, the input principal is canonical. */ +- if (context->dns_canonicalize_hostname != CANONHOST_FALLBACK || +- iter->princ->type != KRB5_NT_SRV_HST || iter->princ->length != 2 || ++ /* If the hostname isn't from krb5_sname_to_principal(), the input ++ * principal is canonical. */ ++ if (iter->princ->type != KRB5_NT_SRV_HST || iter->princ->length != 2 || + iter->princ->data[1].length == 0) { + *princ_out = (step == 1) ? iter->princ : NULL; + return 0; + } + ++ /* If we're not doing fallback, the hostname is canonical, but we may need ++ * to substitute the default realm. */ ++ if (context->dns_canonicalize_hostname != CANONHOST_FALLBACK) { ++ if (step > 1) ++ return 0; ++ iter->copy = *iter->princ; ++ if (iter->subst_defrealm && iter->copy.realm.length == 0) { ++ ret = krb5_get_default_realm(context, &iter->realm); ++ if (ret) ++ return ret; ++ iter->copy = *iter->princ; ++ iter->copy.realm = string2data(iter->realm); ++ } ++ *princ_out = &iter->copy; ++ return 0; ++ } ++ + /* Canonicalize without DNS at step 1, with DNS at step 2. */ + if (step > 2) + return 0; diff --git a/Move-some-dejagnu-kadmin-tests-to-Python-tests.patch b/Move-some-dejagnu-kadmin-tests-to-Python-tests.patch new file mode 100644 index 0000000..9334c19 --- /dev/null +++ b/Move-some-dejagnu-kadmin-tests-to-Python-tests.patch @@ -0,0 +1,1750 @@ +From 9b3d8b9c395bf1a889ea6d6439dc3543c680480d Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Thu, 22 Apr 2021 15:51:36 -0400 +Subject: [PATCH] Move some dejagnu kadmin tests to Python tests + +Remove the dejagnu scripts kadmin.exp, pwchange.exp, and pwhist.exp. + +Add a new Python test script t_kadmin.py for the miscellaneous kadmin +tests from kadmin.exp. + +In t_changepw.py, use modprinc +needchange for one of the kinit +password change tests to gain the same coverage as pwchange.exp had, +and add the "password changes are usable by kinit" tests from +kadmin.exp. + +In t_policy.py, add the ticket 929 regression tests from kadmin.exp +and the ticket 2841 regression tests from pwhist.exp. + +(cherry picked from commit 8027531caf6911bb07bf13de087da0e6bef5a348) +--- + src/tests/Makefile.in | 1 + + src/tests/dejagnu/krb-standalone/kadmin.exp | 1133 ----------------- + src/tests/dejagnu/krb-standalone/pwchange.exp | 145 --- + src/tests/dejagnu/krb-standalone/pwhist.exp | 217 ---- + src/tests/t_changepw.py | 34 +- + src/tests/t_kadmin.py | 54 + + src/tests/t_policy.py | 62 + + 7 files changed, 143 insertions(+), 1503 deletions(-) + delete mode 100644 src/tests/dejagnu/krb-standalone/kadmin.exp + delete mode 100644 src/tests/dejagnu/krb-standalone/pwchange.exp + delete mode 100644 src/tests/dejagnu/krb-standalone/pwhist.exp + create mode 100644 src/tests/t_kadmin.py + +diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in +index 6b7749129..ab416cc5f 100644 +--- a/src/tests/Makefile.in ++++ b/src/tests/Makefile.in +@@ -147,6 +147,7 @@ check-pytests: unlockiter s4u2self + $(RUNPYTEST) $(srcdir)/t_referral.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_skew.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_keytab.py $(PYTESTFLAGS) ++ $(RUNPYTEST) $(srcdir)/t_kadmin.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadmin_acl.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadmin_parsing.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kdb.py $(PYTESTFLAGS) +diff --git a/src/tests/dejagnu/krb-standalone/kadmin.exp b/src/tests/dejagnu/krb-standalone/kadmin.exp +deleted file mode 100644 +index fa50a61fb..000000000 +--- a/src/tests/dejagnu/krb-standalone/kadmin.exp ++++ /dev/null +@@ -1,1133 +0,0 @@ +-# Kerberos kadmin test. +-# This is a DejaGnu test script. +-# This script tests Kerberos kadmin5 using kadmin.local as verification. +- +-#++ +-# kadmin_add - Test add new v5 principal function of kadmin. +-# +-# Adds principal $pname with password $password. Returns 1 on success. +-#-- +-proc kadmin_add { pname password } { +- global REALMNAME +- global KADMIN +- global KADMIN_LOCAL +- global KEY +- global spawn_id +- global tmppwd +- +- set good 0 +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin add $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin add $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin add $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*:" { +- send "adminpass$KEY\r" +- } +- expect "Enter password for principal \"$pname@$REALMNAME\":" { send "$password\r" } +- expect "Re-enter password for principal \"$pname@$REALMNAME\":" { send "$password\r" } +- expect "Principal \"$pname@$REALMNAME\" created." { set good 1 } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin add)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- # +- # use kadmin.local to verify that a principal was created and that its +- # salt types are 0 (normal). +- # +- envstack_push +- setup_kerberos_env kdc +- spawn $KADMIN_LOCAL -r $REALMNAME +- envstack_pop +- expect_after { +- -i $spawn_id +- timeout { +- fail "kadmin add $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin add $pname" +- catch "expect_after" +- return 0 +- } +- } +- set good 0 +- expect "kadmin.local: " { send "getprinc $pname\r" } +- expect "Principal: $pname@$REALMNAME" { set good 1 } +- expect "Expiration date:" { verbose "got expiration date" } +- expect "Last password change:" { verbose "got last pwchange" } +- expect "Password expiration date:" { verbose "got pwexpire date" } +- expect "Maximum ticket life:" { verbose "got max life" } +- expect "Maximum renewable life:" { verbose "got max rlife" } +- expect "Last modified:" { verbose "got last modified" } +- expect "Last successful authentication:" { verbose "last succ auth" } +- expect "Last failed authentication:" { verbose "last pw failed" } +- expect "Failed password attempts:" { verbose "num failed attempts" } +- expect "Number of keys:" { verbose "num keys"} +- expect { +- "Key: " { verbose "Key listed" +- exp_continue +- } +- "Attributes:" { verbose "attributes" } +- } +- expect "kadmin.local: " { send "q\r" } +- +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin.local show)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- pass "kadmin add $pname" +- return 1 +- } +- else { +- fail "kadmin add $pname" +- return 0 +- } +- } +- else { +- fail "kadmin add $pname" +- return 0 +- } +-} +- +-#++ +-# kadmin_add_rnd - Test add new v5 principal with random key function. +-# +-# Adds principal $pname with random key. Returns 1 on success. +-#-- +-proc kadmin_add_rnd { pname { flags "" } } { +- global REALMNAME +- global KADMIN +- global KADMIN_LOCAL +- global KEY +- global spawn_id +- global tmppwd +- +- set good 0 +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank -randkey $flags $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin add rnd $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin add_rnd $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin add_rnd $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- expect "Principal \"$pname@$REALMNAME\" created." { set good 1 } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin add_rnd)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- # +- # use kadmin.local to verify that a principal was created and that its +- # salt types are 0 (normal). +- # +- envstack_push +- setup_kerberos_env kdc +- spawn $KADMIN_LOCAL -r $REALMNAME +- envstack_pop +- expect_after { +- -i $spawn_id +- timeout { +- fail "kadmin add_rnd $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin add_rnd $pname" +- catch "expect_after" +- return 0 +- } +- } +- set good 0 +- expect "kadmin.local:" { send "getprinc $pname\r" } +- expect "Principal: $pname@$REALMNAME" { set good 1 } +- expect "kadmin.local:" { send "q\r" } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin.local show)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- pass "kadmin add_rnd $pname" +- return 1 +- } +- else { +- fail "kadmin add_rnd $pname" +- return 0 +- } +- } +- else { +- fail "kadmin add_rnd $pname" +- return 0 +- } +-} +- +-#++ +-# kadmin_show - Test show principal function of kadmin. +-# +-# Retrieves entry for $pname. Returns 1 on success. +-#-- +-proc kadmin_show { pname } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "get_principal $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin show $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin show $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin show $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" +- send "adminpass$KEY\r" +- expect -re "\r.*Principal: $pname@$REALMNAME.*Key: .*Attributes:.*Policy: .*\r" +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin show)" +- catch "close -i $spawn_id" +- pass "kadmin show $pname" +- return 1 +-} +- +-#++ +-# kadmin_cpw - Test change password function of kadmin +-# +-# Change password of $pname to $password. Returns 1 on success. +-#-- +-proc kadmin_cpw { pname password } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "cpw $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin cpw $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin cpw $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin cpw $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- +- expect "Enter password for principal \"$pname@$REALMNAME\":" { send "$password\r" } +- expect "Re-enter password for principal \"$pname@$REALMNAME\":" { send "$password\r" } +- # When in doubt, jam one of these in there. +- expect "\r" +- expect "Password for \"$pname@$REALMNAME\" changed." +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin cpw)" +- catch "close -i $spawn_id" +- pass "kadmin cpw $pname" +- return 1 +-} +- +-#++ +-# kadmin_cpw_rnd - Test change random key function of kadmin. +-# +-# Changes principal $pname's key to a new random key. Returns 1 on success. +-#-- +-proc kadmin_cpw_rnd { pname } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "cpw -randkey $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin cpw_rnd $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin cpw_rnd $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin cpw_rnd $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- # When in doubt, jam one of these in there. +- expect "\r" +- expect "Key for \"$pname@$REALMNAME\" randomized." +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin cpw_rnd)" +- catch "close -i $spawn_id" +- pass "kadmin cpw_rnd $pname" +- return 1 +-} +- +-#++ +-# kadmin_modify - Test modify principal function of kadmin. +-# +-# Modifies principal $pname with flags $flags. Returns 1 on success. +-#-- +-proc kadmin_modify { pname flags } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "modprinc $flags $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin modify $pname ($flags) lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin modify $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin modify $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" +- send "adminpass$KEY\r" +- # When in doubt, jam one of these in there. +- expect "\r" +- expect "Principal \"$pname@$REALMNAME\" modified." +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin modify)" +- catch "close -i $spawn_id" +- pass "kadmin modify $pname" +- return 1 +-} +- +- +-#++ +-# kadmin_list - Test list database function of kadmin. +-# +-# Lists the database and verifies that output matches regular expression +-# "(.*@$REALMNAME)*". Returns 1 on success. +-#-- +-proc kadmin_list { } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- +- # "*" would match everything +- # "*n" should match a few like kadmin/admin but see ticket 5667 +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "get_principals *n" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin ldb lost KDC" +- catch "expect_after" +- return 0 +- } +- "Communication failure" { +- fail "kadmin ldb got RPC error" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin ldb" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin ldb" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- expect -re "\(.*@$REALMNAME\r\n\)+" +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin list)" +- catch "close -i $spawn_id" +- pass "kadmin ldb" +- return 1 +-} +- +-#++ +-# kadmin_extract - Test extract service key function of kadmin. +-# +-# Extracts service key for service name $name instance $instance. Returns +-# 1 on success. +-#-- +-proc kadmin_extract { instance name } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- global tmppwd +- +- catch "exec rm -f $tmppwd/keytab" +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "xst -k $tmppwd/keytab $name/$instance" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin xst $instance $name lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin xst $instance $name" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin xst $instance $name" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin xst)" +- catch "close -i $spawn_id" +- catch "exec rm -f $instance-new-keytab" +- pass "kadmin xst $instance $name" +- return 1 +-} +- +-#++ +-# kadmin_delete - Test delete principal function of kadmin. +-# +-# Deletes principal $pname. Returns 1 on success. +-#-- +-proc kadmin_delete { pname } { +- global REALMNAME +- global KADMIN +- global KADMIN_LOCAL +- global KEY +- global spawn_id +- global tmppwd +- +- set good 0 +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "delprinc -force $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin_delete $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin delprinc $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin delprinc $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- expect "Principal \"$pname@$REALMNAME\" deleted." { set good 1 } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin delprinc)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- # +- # use kadmin.local to verify that the old principal is not present. +- # +- envstack_push +- setup_kerberos_env kdc +- spawn $KADMIN_LOCAL -r $REALMNAME +- envstack_pop +- expect_after { +- -i $spawn_id +- timeout { +- fail "kadmin delprinc $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin delprinc $pname" +- catch "expect_after" +- return 0 +- } +- } +- set good 0 +- expect "kadmin.local: " { send "getprinc $pname\r" } +- expect "Principal does not exist while retrieving \"$pname@$REALMNAME\"." { set good 1 } +- expect "kadmin.local: " { send "quit\r" } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin.local show)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- pass "kadmin delprinc $pname" +- return 1 +- } +- else { +- fail "kadmin delprinc $pname" +- return 0 +- } +- } +- else { +- fail "kadmin delprinc $pname" +- return 0 +- } +-} +- +-#++ +-# kadmin_delete - Test delete principal function of kadmin. +-# +-# Deletes principal $pname. Returns 1 on success. +-#-- +-proc kadmin_delete_locked_down { pname } { +- global REALMNAME +- global KADMIN +- global KADMIN_LOCAL +- global KEY +- global spawn_id +- global tmppwd +- +- # +- # First test that we fail, then unlock and retry +- # +- +- set good 0 +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "delprinc -force $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin_delete $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin delprinc $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin delprinc $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- expect "delete_principal: Operation requires ``delete'' privilege while deleting principal \"$pname@$REALMNAME\"" { set good 1 } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin delprinc)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- # +- # use kadmin.local to remove lockdown. +- # +- envstack_push +- setup_kerberos_env kdc +- spawn $KADMIN_LOCAL -r $REALMNAME +- envstack_pop +- expect_after { +- -i $spawn_id +- timeout { +- fail "kadmin delprinc $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin delprinc $pname" +- catch "expect_after" +- return 0 +- } +- } +- set good 0 +- expect "kadmin.local: " { send "modprinc -lockdown_keys $pname\r" } +- expect "Principal \"$pname@$REALMNAME\" modified." { set good 1 } +- expect "kadmin.local: " { send "quit\r" } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin.local show)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- set good 0 +- if {[kadmin_delete $pname]} { set good 1 } +- } +- if { $good == 1 } { +- pass "kadmin delprinc $pname" +- return 1 +- } +- else { +- fail "kadmin delprinc $pname" +- return 0 +- } +- } +- else { +- fail "kadmin delprinc $pname" +- return 0 +- } +-} +- +-#++ +-# kpasswd_cpw - Test password changing using kpasswd. +-# +-# Change $princ's password from $opw to $npw. Returns 1 on success. +-#-- +-proc kpasswd_cpw { princ opw npw } { +- global KPASSWD +- global REALMNAME +- +- spawn $KPASSWD $princ +- expect_after { +- timeout { +- fail "kpasswd $princ $npw" +-# catch "expect_after" +- return 0 +- } +- eof { +- fail "kpasswd $princ $npw" +-# catch "expect_after" +- return 0 +- } +- } +- +-# expect "Changing password for $princ." +-# expect "Old password:" { send "$opw\r" } +-# expect "New password:" { send "$npw\r" } +-# expect "New password (again):" { send "$npw\r" } +- expect "Password for $princ@$REALMNAME:" { send "$opw\r" } +- expect "Enter new password:" { send "$npw\r" } +- expect "Enter it again:" { send "$npw\r" } +-# expect "Kerberos password changed." +- expect "Password changed." +- expect_after +- expect eof +- +- if ![check_exit_status "kpasswd"] { +- fail "kpasswd $princ $npw" +- return 0 +- } +- pass "kpasswd $princ $npw" +- return 1 +-} +- +-#++ +-# kadmin_addpol - Test add new policy function of kadmin. +-# +-# Adds policy $pname. Returns 1 on success. +-#-- +-proc kadmin_addpol { pname } { +- global REALMNAME +- global KADMIN +- global KADMIN_LOCAL +- global KEY +- global spawn_id +- global tmppwd +- +- set good 0 +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "addpol $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin addpol $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin addpol $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin addpol $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin addpol)" +- catch "close -i $spawn_id" +- # +- # use kadmin.local to verify that a policy was created +- # +- envstack_push +- setup_kerberos_env kdc +- spawn $KADMIN_LOCAL -r $REALMNAME +- envstack_pop +- expect_after { +- -i $spawn_id +- timeout { +- fail "kadmin addpol $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin addpol $pname" +- catch "expect_after" +- return 0 +- } +- } +- set good 0 +- expect "kadmin.local: " { send "getpol $pname\r" } +- expect "Policy: $pname" { set good 1 } +- expect "Maximum password life:" { verbose "got max pw life" } +- expect "Minimum password life:" { verbose "got min pw life" } +- expect "Minimum password length:" { verbose "got min pw length" } +- expect "Minimum number of password character classes:" { +- verbose "got min pw character classes" } +- expect "Number of old keys kept:" { verbose "got num old keys kept" } +- expect "kadmin.local: " { send "q\r" } +- +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin.local showpol)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- pass "kadmin addpol $pname" +- return 1 +- } +- else { +- fail "kadmin addpol $pname" +- return 0 +- } +-} +- +-#++ +-# kadmin_delpol - Test delete policy function of kadmin. +-# +-# Deletes policy $pname. Returns 1 on success. +-#-- +-proc kadmin_delpol { pname } { +- global REALMNAME +- global KADMIN +- global KADMIN_LOCAL +- global KEY +- global spawn_id +- global tmppwd +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "delpol -force $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin_delpol $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin delpol $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin delpol $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin delpol)" +- catch "close -i $spawn_id" +- # +- # use kadmin.local to verify that the old policy is not present. +- # +- envstack_push +- setup_kerberos_env kdc +- spawn $KADMIN_LOCAL -r $REALMNAME +- envstack_pop +- expect_after { +- -i $spawn_id +- timeout { +- fail "kadmin delpol $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin delpol $pname" +- catch "expect_after" +- return 0 +- } +- } +- set good 0 +- expect "kadmin.local: " { send "getpol $pname\r" } +- expect "Policy does not exist while retrieving policy \"$pname\"." { +- set good 1 +- } +- expect "kadmin.local: " { send "quit\r" } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin.local showpol)" +- catch "close -i $spawn_id" +- if { $good == 1 } { +- pass "kadmin delpol $pname" +- return 1 +- } +- else { +- fail "kadmin delpol $pname" +- return 0 +- } +-} +- +-#++ +-# kadmin_listpols - Test list policy database function of kadmin. +-# +-# Lists the policies. Returns 1 on success. +-#-- +-proc kadmin_listpols { } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "get_policies *" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin lpols lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin lpols" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin lpols" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" { +- send "adminpass$KEY\r" +- } +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin listpols)" +- catch "close -i $spawn_id" +- pass "kadmin lpols" +- return 1 +-} +- +-#++ +-# kadmin_modpol - Test modify policy function of kadmin. +-# +-# Modifies policy $pname with flags $flags. Returns 1 on success. +-#-- +-proc kadmin_modpol { pname flags } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "modpol $flags $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin modpol $pname ($flags) lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin modpol $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin modpol $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" +- send "adminpass$KEY\r" +- # When in doubt, jam one of these in there. +- expect "\r" +- # Sadly, kadmin doesn't print a confirmation message for policy operations. +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin modpol)" +- catch "close -i $spawn_id" +- pass "kadmin modpol $pname" +- return 1 +-} +- +-#++ +-# kadmin_showpol - Test show policy function of kadmin. +-# +-# Retrieves entry for $pname. Returns 1 on success. +-#-- +-proc kadmin_showpol { pname } { +- global REALMNAME +- global KADMIN +- global KEY +- global spawn_id +- +- spawn $KADMIN -p krbtest/admin@$REALMNAME -q "get_policy $pname" +- expect_after { +- "Cannot contact any KDC" { +- fail "kadmin showpol $pname lost KDC" +- catch "expect_after" +- return 0 +- } +- timeout { +- fail "kadmin showpol $pname" +- catch "expect_after" +- return 0 +- } +- eof { +- fail "kadmin showpol $pname" +- catch "expect_after" +- return 0 +- } +- } +- expect -re "assword\[^\r\n\]*: *" +- send "adminpass$KEY\r" +- expect -re "\r.*Policy: $pname.*Number of old keys kept: .*\r" +- expect_after +- expect eof +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin showpol)" +- catch "close -i $spawn_id" +- pass "kadmin showpol $pname" +- return 1 +-} +- +-#++ +-# kdestroy +-#-- +-proc kdestroy { } { +- global KDESTROY +- +- spawn $KDESTROY -5 +- if ![check_exit_status "kdestroy"] { +- return 0 +- } +- return 1 +-} +- +-# Wrap the tests in a procedure, so that we can kill the daemons if +-# we get some sort of error. +- +-proc kadmin_test { } { +- global hostname +- +- # Start up the kerberos and kadmind daemons +- if {![start_kerberos_daemons 0] } { +- return +- } +- +- # Test basic kadmin functions. +- if {![kadmin_add v5principal/instance1 v5principal] \ +- || ![kadmin_addpol standardpol] \ +- || ![kadmin_showpol standardpol] \ +- || ![kadmin_listpols] \ +- || ![kadmin_modpol standardpol "-minlength 5"] \ +- || ![kadmin_add v4principal/instance2 v4principal] \ +- || ![kadmin_add_rnd v5random] \ +- || ![kadmin_show v5principal/instance1] \ +- || ![kadmin_show v4principal/instance2] \ +- || ![kadmin_show v5random] \ +- || ![kadmin_cpw v5principal/instance1 faroutman] \ +- || ![kadmin_cpw v4principal/instance2 honkydory] \ +- || ![kadmin_cpw_rnd v5random] \ +- || ![kadmin_modify v5random -allow_tix] \ +- || ![kadmin_modify v5random +allow_tix] \ +- || ![kadmin_modify v5random "-policy standardpol"] \ +- || ![kadmin_list] \ +- || ![kadmin_extract instance1 v5principal] \ +- || ![kadmin_delete v5random] \ +- || ![kadmin_delete v4principal/instance2] \ +- || ![kadmin_delete v5principal/instance1] \ +- || ![kadmin_delpol standardpol]} { +- return +- } +- +-# You cannot extract a v4 key... +-# || ![kadmin_extractv4 instance2 v4principal] \ +- +- # now test kpasswd +- if {![kadmin_add testprinc/instance thisisatest] \ +- || ![kpasswd_cpw testprinc/instance thisisatest anothertest] \ +- || ![kpasswd_cpw testprinc/instance anothertest goredsox] \ +- || ![kadmin_delete testprinc/instance]} { +- return +- } +- +- # now test that we can kinit with principals/passwords. +- # We defer kdestroying until after kpasswd at least once to test FAST automatic use in kpasswd +- if {![kadmin_add testprinc1/instance thisisatest] \ +- || ![kinit testprinc1/instance thisisatest 0] \ +- || ![kpasswd_cpw testprinc1/instance thisisatest anothertest] \ +- || ![kdestroy] \ +- || ![kinit testprinc1/instance anothertest 0] \ +- || ![kdestroy] \ +- || ![kpasswd_cpw testprinc1/instance anothertest goredsox] \ +- || ![kinit testprinc1/instance goredsox 0] \ +- || ![kdestroy] \ +- || ![kadmin_cpw testprinc1/instance betterwork] \ +- || ![kinit testprinc1/instance betterwork 0] \ +- || ![kdestroy] \ +- || ![kadmin_delete testprinc1/instance]} { +- return +- } +- +- # now test modify changes. +- if {![kadmin_add testuser longtestpw] \ +- || ![kinit testuser longtestpw 0] \ +- || ![kdestroy] \ +- || ![kadmin_modify testuser "-maxlife \"2500 seconds\""] \ +- || ![kinit testuser longtestpw 0] \ +- || ![kdestroy] \ +- || ![kadmin_delete testuser]} { +- return +- } +- +- # now test that reducing the history number doesn't make kadmind vulnerable. +- if {![kadmin_addpol crashpol] \ +- || ![kadmin_modpol crashpol "-history 5"] \ +- || ![kadmin_add crash first] \ +- || ![kadmin_modify crash "-policy crashpol"] \ +- || ![kadmin_cpw crash second] \ +- || ![kadmin_cpw crash third] \ +- || ![kadmin_cpw crash fourth] \ +- || ![kadmin_modpol crashpol "-history 3"] \ +- || ![kadmin_cpw crash fifth] \ +- || ![kadmin_delete crash] \ +- || ![kadmin_delpol crashpol]} { +- return +- } +- +- # test retrieval of large number of principals +- # bug [2877] +- for { set i 0 } { $i < 200 } { incr i } { +- if { ![kadmin_add "foo$i" foopass] } { +- return +- } +- } +- +- if { ![kadmin_list] } { +- return +- } +- +- # test fallback to kadmin/hostname +- if {![kadmin_add_rnd kadmin/$hostname] \ +- || ![kadmin_delete_locked_down kadmin/admin] \ +- || ![kadmin_list] \ +- || ![kadmin_add_rnd kadmin/admin -allow_tgs_req] \ +- || ![kadmin_list]} { +- return +- } +- +- verbose "kadmin_test succeeded" +-} +- +-run_once kadmin { +- # Set up the kerberos database. +- if {![get_hostname] \ +- || ![setup_kerberos_files] \ +- || ![setup_kerberos_env] \ +- || ![setup_kerberos_db 0]} { +- return +- } +- +- # Run the test. +- set status [catch kadmin_test msg] +- +- # Shut down the kerberos daemons and the rsh daemon. +- stop_kerberos_daemons +- +- if { $status != 0 } { +- send_error "ERROR: error in kadmin.exp\n" +- send_error "$msg\n" +- exit 1 +- } +-} +diff --git a/src/tests/dejagnu/krb-standalone/pwchange.exp b/src/tests/dejagnu/krb-standalone/pwchange.exp +deleted file mode 100644 +index 010e8344a..000000000 +--- a/src/tests/dejagnu/krb-standalone/pwchange.exp ++++ /dev/null +@@ -1,145 +0,0 @@ +-# Password-changing Kerberos test. +-# This is a DejaGnu test script. +- +-# We are about to start up a couple of daemon processes. We do all +-# the rest of the tests inside a proc, so that we can easily kill the +-# processes when the procedure ends. +- +-proc kinit_expecting_pwchange { name pass newpass } { +- global REALMNAME +- global KINIT +- global spawn_id +- +- # Use kinit to get a ticket. +- # +- # For now always get forwardable tickets. Later when we need to make +- # tests that distinguish between forwardable tickets and otherwise +- # we should but another option to this proc. --proven +- # +- spawn $KINIT -5 -f $name@$REALMNAME +- expect { +- "Password for $name@$REALMNAME:" { +- verbose "kinit started" +- } +- timeout { +- fail "kinit" +- return 0 +- } +- eof { +- fail "kinit" +- return 0 +- } +- } +- send "$pass\r" +- expect { +- "Enter new password: " { } +- timeout { +- fail "kinit (new password prompt)" +- return 0 +- } +- eof { +- fail "kinit (new password prompt)" +- return 0 +- } +- } +- send "$newpass\r" +- expect { +- " again: " { } +- timeout { +- fail "kinit (new password prompt2)" +- return 0 +- } +- eof { +- fail "kinit (new password prompt2)" +- return 0 +- } +- } +- send "$newpass\r" +- expect eof +- if ![check_exit_status kinit] { +- return 0 +- } +- +- return 1 +-} +- +-proc doit { } { +- global REALMNAME +- global KLIST +- global KDESTROY +- global KEY +- global KADMIN_LOCAL +- global KTUTIL +- global hostname +- global tmppwd +- global spawn_id +- global supported_enctypes +- global KRBIV +- global portbase +- global mode +- +- # Start up the kerberos and kadmind daemons. +- if ![start_kerberos_daemons 0] { +- return +- } +- +- # Use kadmin to add a key. +- if ![add_kerberos_key pwchanger 0] { +- return +- } +- +- setup_kerberos_env kdc +- spawn $KADMIN_LOCAL -q "modprinc +needchange pwchanger" +- catch expect_after +- expect { +- timeout { +- fail "kadmin.local modprinc +needchange" +- } +- eof { +- pass "kadmin.local modprinc +needchange" +- } +- } +- set k_stat [wait -i $spawn_id] +- verbose "wait -i $spawn_id returned $k_stat (kadmin modprinc +needchange)" +- catch "close -i $spawn_id" +- +- setup_kerberos_env client +- if ![kinit_expecting_pwchange pwchanger pwchanger$KEY floople] { +- return +- } +- pass "kinit (password change)" +- if ![kinit pwchanger floople 0] { +- return +- } +- pass "kinit (new password)" +- +- # Destroy the ticket. +- spawn $KDESTROY -5 +- if ![check_exit_status "kdestroy"] { +- return +- } +- pass "kdestroy" +-} +- +-run_once pwchange { +- # Set up the Kerberos files and environment. +- if {![get_hostname] || ![setup_kerberos_files] || ![setup_kerberos_env]} { +- return +- } +- +- # Initialize the Kerberos database. The argument tells +- # setup_kerberos_db that it is being called from here. +- if ![setup_kerberos_db 0] { +- return +- } +- +- set status [catch doit msg] +- +- stop_kerberos_daemons +- +- if { $status != 0 } { +- send_error "ERROR: error in pwchange.exp\n" +- send_error "$msg\n" +- exit 1 +- } +-} +diff --git a/src/tests/dejagnu/krb-standalone/pwhist.exp b/src/tests/dejagnu/krb-standalone/pwhist.exp +deleted file mode 100644 +index ed7a3771a..000000000 +--- a/src/tests/dejagnu/krb-standalone/pwhist.exp ++++ /dev/null +@@ -1,217 +0,0 @@ +-# password history tests +- +-# one *non-interactive* kadmin.local request +-proc onerq { rq pname str {flags ""} } { +- global REALMNAME +- global KADMIN_LOCAL +- +- spawn $KADMIN_LOCAL -r $REALMNAME -q "$rq $flags $pname" +- expect_after { +- timeout { +- verbose "kadmin.local $rq $flags $pname timed out" +- catch expect_after +- kill [exp_pid] +- close +- expect eof +- wait +- return 0 +- } eof { +- verbose "kadmin.local $rq $flags $pname got EOF" +- catch expect_after +- wait +- return 0 +- } +- } +- expect $str +- expect_after +- expect eof +- wait +- return 1 +-} +- +-proc addprinc { pname pw } { +- global REALMNAME +- +- return [onerq addprinc $pname \ +- "Principal \"$pname@$REALMNAME\" created." "-pw $pw"] +-} +- +-proc delprinc { pname } { +- global REALMNAME +- return [onerq delprinc $pname \ +- "Principal \"$pname@$REALMNAME\" deleted." "-force"] +-} +- +-proc cpw { pname pw } { +- global REALMNAME +- +- return [onerq cpw $pname \ +- "Password for \"$pname@$REALMNAME\" changed." "-pw $pw"] +-} +- +-proc modprinc { pname flags } { +- global REALMNAME +- +- return [onerq modprinc $pname \ +- "Principal \"$pname@$REALMNAME\" modified." $flags] +-} +- +-proc addpol { pname } { +- if ![onerq addpol $pname ""] { +- return 0 +- } +- return [onerq getpol $pname "Policy: $pname"] +-} +- +-proc delpol { pname } { +- onerq delpol $pname "" -force +- return [onerq getpol $pname \ +- "Policy does not exist while retrieving policy \"$pname\"."] +-} +- +-proc modpol { pname flags } { +- return [onerq modpol $pname "" $flags] +-} +- +-# Mandatory command must return true. +-# Issues a break in its parent on failure. +-proc mustrun { cmd } { +- if ![eval $cmd] { +- perror "mandatory command failed: $cmd" +- uplevel break +- } +-} +- +-# Fail test if command fails. +-# Issues a break in its parent on failure. +-proc chkpass { cmd } { +- upvar test test +- if ![eval $cmd] { +- verbose "unexpected failure: $cmd" +- fail $test +- uplevel break +- } +-} +- +-# Fail test if command succeeds. +-# Issues a break in its parent on failure. +-proc chkfail { cmd } { +- upvar test test +- if [eval $cmd] { +- verbose "unexpected success: $cmd" +- fail $test +- uplevel break +- } +-} +- +-# wrapper to run command (actually usually sequence of commands) +-# +-# If any part of CMD throws an exception, set failall, otherwise pass. +-# If failall is already true, report unresolved. +-proc wraptest { test cmd } { +- upvar failall failall +- if $failall { +- unresolved $test +- return +- } +- if [catch $cmd] { +- set failall 1 +- } else { +- pass $test +- } +-} +- +-run_once pwhist { +- # Set up the kerberos database. +- if {![get_hostname] \ +- || ![setup_kerberos_files] \ +- || ![setup_kerberos_env kdc] \ +- || ![setup_kerberos_db 0]} { +- return +- } +- +- set failall 0 +- wraptest "nkeys=1, nhist=3" { +- mustrun { addpol crashpol } +- mustrun { modpol crashpol "-history 3"} +- mustrun { addprinc crash 1111 } +- mustrun { modprinc crash "-policy crashpol" } +- chkpass { cpw crash 2222 } +- chkfail { cpw crash 2222 } +- chkfail { cpw crash 1111 } +- } +- verbose {old_keys [ 1111 ->[] ]} +- +- # The following will result in reading/writing past array bounds if +- # add_to_history() is not patched. +- # +- # NOTE: A pass from this test does not mean the bug isn't present; +- # check with Purify, valgrind, etc. +- wraptest "array bounds ok on nkeys=1, nhist 3->2" { +- mustrun { modpol crashpol "-history 2" } +- chkpass { cpw crash 3333 } +- } +- verbose {old_keys [ ->2222 ]} +- +- wraptest "verify nhist=2" { +- mustrun { delprinc crash } +- mustrun { addprinc crash 1111 } +- mustrun { modprinc crash "-policy crashpol" } +- chkpass { cpw crash 2222 } +- chkfail { cpw crash 2222 } +- chkfail { cpw crash 1111 } +- } +- verbose {old_keys [ ->1111 ]} +- +- # The following will fail if growing the history array causes an extra +- # key to be lost due to failure to shift entries. +- wraptest "grow nhist 2->3" { +- mustrun { modpol crashpol "-history 3" } +- chkpass { cpw crash 3333 } +- chkfail { cpw crash 3333 } +- chkfail { cpw crash 2222 } +- chkfail { cpw crash 1111 } +- } +- verbose {old_keys [ 2222 ->1111 ]} +- +- wraptest "grow nhist 3->4" { +- mustrun { modpol crashpol "-history 4" } +- chkfail { cpw crash 3333 } +- chkfail { cpw crash 2222 } +- chkfail { cpw crash 1111 } +- chkpass { cpw crash 4444 } +- chkfail { cpw crash 3333 } +- chkfail { cpw crash 2222 } +- chkfail { cpw crash 1111 } +- } +- verbose {old_keys [ 2222 3333 ->1111 ]} +- wraptest "shrink nhist 4->3" { +- mustrun { modpol crashpol "-history 3" } +- chkfail { cpw crash 4444 } +- chkfail { cpw crash 3333 } +- chkfail { cpw crash 2222 } +- chkfail { cpw crash 1111 } +- chkpass { cpw crash 5555 } +- } +- verbose {old_keys [ 4444 ->3333 ]} +- wraptest "verify nhist=3" { +- chkfail { cpw crash 5555 } +- chkfail { cpw crash 4444 } +- chkfail { cpw crash 3333 } +- chkpass { cpw crash 2222 } +- } +- verbose {old_keys [ ->4444 5555 ]} +- wraptest "shrink nhist 3->2" { +- mustrun { modpol crashpol "-history 2" } +- chkfail { cpw crash 2222 } +- chkfail { cpw crash 5555 } +- chkfail { cpw crash 4444 } +- chkpass { cpw crash 3333 } +- } +- verbose {old_keys [ ->2222 ]} +- +- delprinc crash +- delpol crashpol +- +- stop_kerberos_daemons +-} +diff --git a/src/tests/t_changepw.py b/src/tests/t_changepw.py +index 573bdbd49..bf8e3a9eb 100755 +--- a/src/tests/t_changepw.py ++++ b/src/tests/t_changepw.py +@@ -1,23 +1,24 @@ + from k5test import * + +-# This file is intended to cover any password-changing mechanism. For +-# now it only contains a regression test for #7868. +- + realm = K5Realm(create_host=False, get_creds=False, start_kadmind=True) ++realm.prep_kadmin() + + # Mark a principal as expired and change its password through kinit. ++mark('password change via kinit') + realm.run([kadminl, 'modprinc', '-pwexpire', '1 day ago', 'user']) + pwinput = password('user') + '\nabcd\nabcd\n' + realm.run([kinit, realm.user_princ], input=pwinput) + +-# Do the same thing with FAST, with tracing turned on. +-realm.run([kadminl, 'modprinc', '-pwexpire', '1 day ago', 'user']) ++# Regression test for #7868 (preauth options ignored when ++# krb5_get_init_creds_password() initiates a password change). This ++# time use the REQUIRES_PWCHANGE bit instead of the password ++# expiration time. ++mark('password change via kinit with FAST') ++realm.run([kadminl, 'modprinc', '+needchange', 'user']) + pwinput = 'abcd\nefgh\nefgh\n' + out, trace = realm.run([kinit, '-T', realm.ccache, realm.user_princ], + input=pwinput, return_trace=True) +- +-# Read the trace and check that FAST was used when getting the +-# kadmin/changepw ticket. ++# Check that FAST was used when getting the kadmin/changepw ticket. + getting_changepw = fast_used_for_changepw = False + for line in trace.splitlines(): + if 'Getting initial credentials for user@' in line: +@@ -29,4 +30,21 @@ for line in trace.splitlines(): + if not fast_used_for_changepw: + fail('FAST was not used to get kadmin/changepw ticket') + ++# Test that passwords specified via kadmin and kpasswd are usable with ++# kinit. ++mark('password change usability by kinit') ++realm.run([kadminl, 'addprinc', '-pw', 'pw1', 'testprinc']) ++# Run kpasswd with an active cache to exercise automatic FAST use. ++realm.kinit('testprinc', 'pw1') ++realm.run([kpasswd, 'testprinc'], input='pw1\npw2\npw2\n') ++realm.kinit('testprinc', 'pw2') ++realm.run([kdestroy]) ++realm.run([kpasswd, 'testprinc'], input='pw2\npw3\npw3\n') ++realm.kinit('testprinc', 'pw3') ++realm.run([kdestroy]) ++realm.run_kadmin(['cpw', '-pw', 'pw4', 'testprinc']) ++realm.kinit('testprinc', 'pw4') ++realm.run([kdestroy]) ++realm.run([kadminl, 'delprinc', 'testprinc']) ++ + success('Password change tests') +diff --git a/src/tests/t_kadmin.py b/src/tests/t_kadmin.py +new file mode 100644 +index 000000000..fe6a3cc2e +--- /dev/null ++++ b/src/tests/t_kadmin.py +@@ -0,0 +1,54 @@ ++from k5test import * ++ ++realm = K5Realm(start_kadmind=True) ++ ++# Create a principal. Test -q option and keyboard entry of the admin ++# password and principal password. Verify creation with kadmin.local. ++realm.run([kadmin, '-q', 'addprinc princ/pw'], ++ input=password('admin') + '\npw1\npw1\n') ++realm.run([kadminl, 'getprinc', 'princ/pw'], ++ expected_msg='Principal: princ/pw@KRBTEST.COM') ++ ++# Run the remaining tests with a cache for efficiency. ++realm.prep_kadmin() ++ ++realm.run_kadmin(['addpol', 'standardpol']) ++realm.run_kadmin(['listpols'], expected_msg='standardpol') ++realm.run_kadmin(['modpol', '-minlength', '5', 'standardpol']) ++realm.run_kadmin(['getpol', 'standardpol'], ++ expected_msg='Minimum password length: 5') ++ ++realm.run_kadmin(['addprinc', '-randkey', 'princ/random']) ++realm.run([kadminl, 'getprinc', 'princ/random'], ++ expected_msg='Principal: princ/random@KRBTEST.COM') ++ ++realm.run_kadmin(['cpw', 'princ/pw'], input='newpw\nnewpw\n') ++realm.run_kadmin(['cpw', '-randkey', 'princ/random']) ++ ++realm.run_kadmin(['modprinc', '-allow_tix', 'princ/random']) ++realm.run_kadmin(['modprinc', '+allow_tix', 'princ/random']) ++realm.run_kadmin(['modprinc', '-policy', 'standardpol', 'princ/random']) ++ ++realm.run_kadmin(['listprincs'], expected_msg='princ/random@KRBTEST.COM') ++ ++realm.run_kadmin(['ktadd', 'princ/pw']) ++ ++realm.run_kadmin(['delprinc', 'princ/random']) ++realm.run([kadminl, 'getprinc', 'princ/random'], expected_code=1, ++ expected_msg='Principal does not exist') ++realm.run_kadmin(['delprinc', 'princ/pw']) ++realm.run([kadminl, 'getprinc', 'princ/pw'], expected_code=1, ++ expected_msg='Principal does not exist') ++ ++realm.run_kadmin(['delpol', 'standardpol']) ++realm.run([kadminl, 'getpol', 'standardpol'], expected_code=1, ++ expected_msg='Policy does not exist') ++ ++# Regression test for #2877 (fixed-sized GSSRPC buffers can't ++# accomodate large listprinc results). ++mark('large listprincs result') ++for i in range(200): ++ realm.run_kadmin(['addprinc', '-randkey', 'foo%d' % i]) ++realm.run_kadmin(['listprincs'], expected_msg='foo199') ++ ++success('kadmin and kpasswd tests') +diff --git a/src/tests/t_policy.py b/src/tests/t_policy.py +index 5a0c06b86..2bb4f5f18 100755 +--- a/src/tests/t_policy.py ++++ b/src/tests/t_policy.py +@@ -25,6 +25,68 @@ realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], expected_code=1, + realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser']) + realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser']) + ++# Regression test for #929 (kadmind crash with more historical ++# passwords in a principal entry than current policy history setting). ++mark('password history (policy value reduced below current array size)') ++realm.run([kadminl, 'addpol', '-history', '5', 'histpol']) ++realm.addprinc('histprinc', 'first') ++realm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) ++realm.run([kadminl, 'cpw', '-pw', 'second', 'histprinc']) ++realm.run([kadminl, 'cpw', '-pw', 'third', 'histprinc']) ++realm.run([kadminl, 'cpw', '-pw', 'fourth', 'histprinc']) ++realm.run([kadminl, 'modpol', '-history', '3', 'histpol']) ++realm.run([kadminl, 'cpw', '-pw', 'fifth', 'histprinc']) ++realm.run([kadminl, 'delprinc', 'histprinc']) ++ ++# Regression test for #2841 (heap buffer overflow when policy history ++# value is reduced to match the number of historical passwords for a ++# principal). ++mark('password history (policy value reduced to current array size)') ++def histfail(*pwlist): ++ for pw in pwlist: ++ realm.run([kadminl, 'cpw', '-pw', pw, 'histprinc'], expected_code=1, ++ expected_msg='Cannot reuse password') ++realm.run([kadminl, 'modpol', '-history', '3', 'histpol']) ++realm.addprinc('histprinc', '1111') ++realm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) ++realm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) ++histfail('2222', '1111') ++realm.run([kadminl, 'modpol', '-history', '2', 'histpol']) ++realm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) ++ ++# Test that the history array is properly resized if the policy ++# history value is increased after the array is filled. ++mark('password history (policy value increase)') ++realm.run([kadminl, 'delprinc', 'histprinc']) ++realm.addprinc('histprinc', '1111') ++realm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) ++realm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) ++histfail('2222', '1111') ++realm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc'], expected_code=1, ++ expected_msg='Cannot reuse password') ++realm.run([kadminl, 'cpw', '-pw', '1111', 'histprinc'], expected_code=1, ++ expected_msg='Cannot reuse password') ++realm.run([kadminl, 'modpol', '-history', '3', 'histpol']) ++realm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) ++histfail('3333', '2222', '1111') ++realm.run([kadminl, 'modpol', '-history', '4', 'histpol']) ++histfail('3333', '2222', '1111') ++realm.run([kadminl, 'cpw', '-pw', '4444', 'histprinc']) ++histfail('4444', '3333', '2222', '1111') ++ ++# Test that when the policy history value is reduced, all currently ++# known old passwords still fail until the next password change, after ++# which the new number of old passwords fails (but no more). ++mark('password history (policy value reduction)') ++realm.run([kadminl, 'modpol', '-history', '3', 'histpol']) ++histfail('4444', '3333', '2222', '1111') ++realm.run([kadminl, 'cpw', '-pw', '5555', 'histprinc']) ++histfail('5555', '3333', '3333') ++realm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) ++realm.run([kadminl, 'modpol', '-history', '2', 'histpol']) ++histfail('2222', '5555', '4444') ++realm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) ++ + # Test references to nonexistent policies. + mark('nonexistent policy references') + realm.run([kadminl, 'addprinc', '-randkey', '-policy', 'newpol', 'newuser']) diff --git a/krb5.spec b/krb5.spec index b59f39c..25d282e 100644 --- a/krb5.spec +++ b/krb5.spec @@ -42,7 +42,7 @@ Summary: The Kerberos network authentication system Name: krb5 Version: 1.19.1 -Release: %{?zdpd}9%{?dist} +Release: %{?zdpd}10%{?dist} # rharwood has trust path to signing key and verifies on check-in Source0: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz @@ -79,6 +79,10 @@ Patch13: Make-KCM-iteration-fallback-work-with-sssd-kcm.patch Patch14: Use-KCM_OP_RETRIEVE-in-KCM-client.patch Patch15: Fix-KCM-retrieval-support-for-sssd.patch Patch16: Fix-doc-build-for-Sphinx-4.0.patch +Patch17: Move-some-dejagnu-kadmin-tests-to-Python-tests.patch +Patch18: Fix-some-principal-realm-canonicalization-cases.patch +Patch19: Allow-kinit-with-keytab-to-defer-canonicalization.patch +Patch20: Fix-kadmin-k-with-fallback-or-referral-realm.patch License: MIT URL: https://web.mit.edu/kerberos/www/ @@ -641,6 +645,9 @@ exit 0 %{_libdir}/libkadm5srv_mit.so.* %changelog +* Wed Jun 09 2021 Robbie Harwood - 1.19.1-10 +- Fix three canonicalization cases for fallback + * Wed Jun 02 2021 Robbie Harwood - 1.19.1-9 - Fix doc build for Sphinx 4.0