--- /dev/null
+# 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
+ }
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+ || ![setup_kerberos_files] \
+ || ![setup_kerberos_env] \
+ || ![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