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'])