krb5/Move-some-dejagnu-kadmin-tests-to-Python-tests.patch
2021-06-17 17:47:21 -04:00

1752 lines
47 KiB
Diff

From a76c4be37be92c02b5ac698ff3c06e2124030427 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
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)
(cherry picked from commit 9b3d8b9c395bf1a889ea6d6439dc3543c680480d)
---
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'])