krb5 commit: Rewrite not-yet-covered dejagnu tests in Python

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/bbce6a8beee93030b65edf3a6612064c621a34d9
commit bbce6a8beee93030b65edf3a6612064c621a34d9
Author: Greg Hudson <[email protected]>
Date:   Thu May 20 17:31:49 2021 -0400

    Rewrite not-yet-covered dejagnu tests in Python
    
    Remove the dejagnu scripts gssapi.exp, princexpire.exp, sample.exp,
    simple.exp, and tcp.exp.
    
    Add server output checking to t_gss_sample.py to match the checks in
    gssapi.exp.
    
    Add a test to t_general.py matching the #6428 regression test in
    princexpire.exp.
    
    Add new test scripts t_sample.py and t_simply.py for the appl/sample
    and appl/simple applications, to match sample.exp and simple.exp.
    Adjust the simple and sample servers to allow for startup detection
    when stdout is a pipe.  Both of these test servers exit after one
    client execution; add a k5test function await_daemon_exit() to allow
    the daemon exit status to be checked without sending a kill signal.
    Change start_in_inetd() not to require the program name to be
    specified twice.  Adjust the existing t_user2user.py for the
    aforementioned changes.
    
    Add a TCP test to t_bigreply.py to match the oversized-TCP-request
    test in tcp.exp.  The existing t_bigreply.py test already covers a
    successful TCP request.

 src/appl/gss-sample/t_gss_sample.py              |   11 +
 src/appl/sample/Makefile.in                      |    3 +
 src/appl/sample/sserver/sserver.c                |    4 +
 src/appl/sample/t_sample.py                      |   22 ++
 src/appl/simple/Makefile.in                      |    3 +
 src/appl/simple/server/sim_server.c              |    1 +
 src/appl/simple/t_simple.py                      |   34 +++
 src/appl/user_user/t_user2user.py                |    5 +-
 src/kdc/t_bigreply.py                            |   14 +
 src/tests/dejagnu/krb-standalone/gssapi.exp      |  332 ----------------------
 src/tests/dejagnu/krb-standalone/princexpire.exp |  105 -------
 src/tests/dejagnu/krb-standalone/sample.exp      |  217 --------------
 src/tests/dejagnu/krb-standalone/simple.exp      |  216 --------------
 src/tests/dejagnu/krb-standalone/tcp.exp         |  112 --------
 src/tests/t_general.py                           |   10 +
 src/util/k5test.py                               |    9 +-
 16 files changed, 113 insertions(+), 985 deletions(-)

diff --git a/src/appl/gss-sample/t_gss_sample.py b/src/appl/gss-sample/t_gss_sample.py
index 77f3978..3608359 100755
--- a/src/appl/gss-sample/t_gss_sample.py
+++ b/src/appl/gss-sample/t_gss_sample.py
@@ -36,6 +36,17 @@ def run_client_server(realm, options, server_options, **kwargs):
     server = realm.start_server(server_args, 'starting...')
     realm.run([gss_client, '-port', portstr] + options +
               [hostname, 'host', 'testmsg'], **kwargs)
+
+    seen1 = seen2 = False
+    while 'expected_code' not in kwargs and not (seen1 and seen2):
+        line = server.stdout.readline()
+        if line == '':
+            fail('gss-server process exited unexpectedly')
+        if line == 'Accepted connection: "[email protected]"\n':
+            seen1 = True
+        if line == 'Received message: "testmsg"\n':
+            seen2 = True
+
     stop_daemon(server)
 
 # Run a gss-server and gss-client process, and verify that gss-client
diff --git a/src/appl/sample/Makefile.in b/src/appl/sample/Makefile.in
index 63ac42e..50caa86 100644
--- a/src/appl/sample/Makefile.in
+++ b/src/appl/sample/Makefile.in
@@ -1,3 +1,6 @@
 mydir=appl$(S)sample
 SUBDIRS = sclient sserver
 BUILDTOP=$(REL)..$(S)..
+
+check-pytests:
+	$(RUNPYTEST) $(srcdir)/t_sample.py $(PYTESTFLAGS)
diff --git a/src/appl/sample/sserver/sserver.c b/src/appl/sample/sserver/sserver.c
index ffbd883..807e1ef 100644
--- a/src/appl/sample/sserver/sserver.c
+++ b/src/appl/sample/sserver/sserver.c
@@ -179,6 +179,10 @@ main(int argc, char *argv[])
             syslog(LOG_ERR, "listen: %m");
             exit(3);
         }
+
+        printf("starting...\n");
+        fflush(stdout);
+
         if ((acc = accept(sock, (struct sockaddr *)&peername, &namelen)) == -1){
             syslog(LOG_ERR, "accept: %m");
             exit(3);
diff --git a/src/appl/sample/t_sample.py b/src/appl/sample/t_sample.py
new file mode 100644
index 0000000..1b75fa2
--- /dev/null
+++ b/src/appl/sample/t_sample.py
@@ -0,0 +1,22 @@
+from k5test import *
+
+sclient = os.path.join(buildtop, 'appl', 'sample', 'sclient', 'sclient')
+sserver = os.path.join(buildtop, 'appl', 'sample', 'sserver', 'sserver')
+
+for realm in multipass_realms(create_host=False):
+    server_princ = 'sample/%s@%s' % (hostname, realm.realm)
+    realm.addprinc(server_princ)
+    realm.extract_keytab(server_princ, realm.keytab)
+
+    portstr = str(realm.server_port())
+    server = realm.start_server([sserver, '-p', portstr], 'starting...')
+    out = realm.run([sclient, hostname, portstr],
+                    expected_msg='You are [email protected]')
+    await_daemon_exit(server)
+
+    server = realm.start_in_inetd([sserver])
+    out = realm.run([sclient, hostname, portstr],
+                    expected_msg='You are [email protected]')
+    await_daemon_exit(server)
+
+success('sim_client/sim_server tests')
diff --git a/src/appl/simple/Makefile.in b/src/appl/simple/Makefile.in
index a605616..5b9af1b 100644
--- a/src/appl/simple/Makefile.in
+++ b/src/appl/simple/Makefile.in
@@ -1,3 +1,6 @@
 mydir=appl$(S)simple
 SUBDIRS = client server
 BUILDTOP=$(REL)..$(S)..
+
+check-pytests:
+	$(RUNPYTEST) $(srcdir)/t_simple.py $(PYTESTFLAGS)
diff --git a/src/appl/simple/server/sim_server.c b/src/appl/simple/server/sim_server.c
index ed383a0..093ed55 100644
--- a/src/appl/simple/server/sim_server.c
+++ b/src/appl/simple/server/sim_server.c
@@ -161,6 +161,7 @@ main(int argc, char *argv[])
     }
 
     printf("starting...\n");
+    fflush(stdout);
 
 #ifdef DEBUG
     printf("socket has port # %d\n", ntohs(s_sock.sin_port));
diff --git a/src/appl/simple/t_simple.py b/src/appl/simple/t_simple.py
new file mode 100644
index 0000000..b720732
--- /dev/null
+++ b/src/appl/simple/t_simple.py
@@ -0,0 +1,34 @@
+from k5test import *
+
+sim_client = os.path.join(buildtop, 'appl', 'simple', 'client', 'sim_client')
+sim_server = os.path.join(buildtop, 'appl', 'simple', 'server', 'sim_server')
+
+for realm in multipass_realms(create_host=False):
+    server_princ = 'sample/%s@%s' % (hostname, realm.realm)
+    realm.addprinc(server_princ)
+    realm.extract_keytab(server_princ, realm.keytab)
+
+    portstr = str(realm.server_port())
+    server = realm.start_server([sim_server, '-p', portstr], 'starting...')
+
+    out = realm.run([sim_client, '-p', portstr, hostname])
+    if ('Sent checksummed message:' not in out or
+        'Sent encrypted message:' not in out):
+        fail('Expected client messages not seen')
+
+    # sim_server exits after one client execution, so we can read
+    # until it closes stdout.
+    seen1 = seen2 = seen3 = False
+    for line in server.stdout:
+        if line == 'Got authentication info from [email protected]\n':
+            seen1 = True
+        if line == "Safe message is: 'hi there!'\n":
+            seen2 = True
+        if line == "Decrypted message is: 'hi there!'\n":
+            seen3 = True
+    if not (seen1 and seen2 and seen3):
+        fail('Expected server messages not seen')
+
+    await_daemon_exit(server)
+
+success('sim_client/sim_server tests')
diff --git a/src/appl/user_user/t_user2user.py b/src/appl/user_user/t_user2user.py
index 2c054f1..9c96759 100755
--- a/src/appl/user_user/t_user2user.py
+++ b/src/appl/user_user/t_user2user.py
@@ -5,13 +5,14 @@ debug_compiled=1
 
 for realm in multipass_realms():
     if debug_compiled == 0:
-        realm.start_in_inetd(['./uuserver', 'uuserver'], port=9999)
+        server = realm.start_in_inetd(['./uuserver'], port=9999)
     else:
-        srv_output = realm.start_server(['./uuserver', '9999'], 'Server started')
+        server = realm.start_server(['./uuserver', '9999'], 'Server started')
 
     msg = 'uu-client: server says "Hello, other end of connection."'
     realm.run(['./uuclient', hostname, 'testing message', '9999'],
               expected_msg=msg)
 
+    await_daemon_exit(server)
 
 success('User-2-user test programs')
diff --git a/src/kdc/t_bigreply.py b/src/kdc/t_bigreply.py
index b630015..ea101ff 100644
--- a/src/kdc/t_bigreply.py
+++ b/src/kdc/t_bigreply.py
@@ -1,4 +1,5 @@
 from k5test import *
+import struct
 
 # Set the maximum UDP reply size very low, so that all replies go
 # through the RESPONSE_TOO_BIG path.
@@ -15,4 +16,17 @@ msgs = ('Sending initial UDP request',
 realm.kinit(realm.user_princ, password('user'), expected_trace=msgs)
 realm.run([kvno, realm.host_princ], expected_trace=msgs)
 
+# Pretend to send an absurdly long request over TCP, and verify that
+# we get back a reply of plausible length to be an encoded
+# KRB_ERR_RESPONSE_TOO_BIG error.
+s = socket.create_connection((hostname, realm.portbase))
+s.sendall(b'\xFF\xFF\xFF\xFF')
+lenbytes = s.recv(4)
+assert(len(lenbytes) == 4)
+resplen, = struct.unpack('>L', lenbytes)
+if resplen < 10:
+    fail('KDC response too short (KRB_ERR_RESPONSE_TOO_BIG error expected)')
+resp = s.recv(resplen)
+assert(len(resp) == resplen)
+
 success('Large KDC replies')
diff --git a/src/tests/dejagnu/krb-standalone/gssapi.exp b/src/tests/dejagnu/krb-standalone/gssapi.exp
deleted file mode 100644
index e3357e7..0000000
--- a/src/tests/dejagnu/krb-standalone/gssapi.exp
+++ /dev/null
@@ -1,332 +0,0 @@
-# Test for the GSS-API.
-# This is a DejaGnu test script.
-# This script tests that the GSS-API tester functions correctly.
-
-# This mostly just calls procedures in test/dejagnu/config/default.exp.
-
-if ![info exists KDESTROY] {
-    set KDESTROY [findfile $objdir/../../clients/kdestroy/kdestroy]
-}
-
-if ![info exists GSSCLIENT] {
-    set GSSCLIENT [findfile $objdir/../../appl/gss-sample/gss-client]
-}
-
-if ![info exists GSSSERVER] {
-    set GSSSERVER [findfile $objdir/../../appl/gss-sample/gss-server]
-}
-
-# 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
-}
-
-#
-# Like kinit in default.exp, but allows us to specify a different ccache.
-#
-proc our_kinit { name pass ccache } {
-    global REALMNAME
-    global KINIT
-    global spawn_id
-
-    # Use kinit to get a ticket.
-    spawn $KINIT -f -5 -c $ccache $name@$REALMNAME
-    expect {
-	"Password for $name@$REALMNAME:" {
-	    verbose "kinit started"
-	}
-	timeout {
-	    fail "kinit"
-	    return 0
-	}
-	eof {
-	    fail "kinit"
-	    return 0
-	}
-    }
-    send "$pass\r"
-    # This last expect seems useless, but without it the test hangs on
-    # AIX.
-    expect {
-        "\r" { }
-    }
-    expect eof
-    if ![check_exit_status kinit] {
-	return 0
-    }
-
-    return 1
-}
-
-#
-# Destroys a particular ccache.
-#
-proc our_kdestroy { ccache } {
-    global KDESTROY
-    global spawn_id
-
-    spawn $KDESTROY -c $ccache
-    if ![check_exit_status "kdestroy"] {
-	return 0
-    }
-    return 1
-}
-
-#
-# Stops the gss-server.
-#
-proc stop_gss_server { } {
-    global gss_server_pid
-    global gss_server_spawn_id
-
-    if [info exists gss_server_pid] {
-	catch "close -i $gss_server_spawn_id"
-	catch "exec kill $gss_server_pid"
-	wait -i $gss_server_spawn_id
-	unset gss_server_pid
-    }
-}
-
-#
-# Restore environment variables possibly set.
-#
-proc gss_restore_env { } {
-    global env
-    global gss_save_ccname
-    global gss_save_ktname
-
-    catch "unset env(KRB5CCNAME)"
-    if [info exists gss_save_ccname] {
-	set env(KRB5CCNAME) $gss_save_ccname
-	unset gss_save_ccname
-    }
-    catch "unset env(KRB5_KTNAME)"
-    if [info exists gss_save_ktname] {
-	set env(KRB5_KTNAME) $gss_save_ktname
-	unset gss_save_ktname
-    }
-}
-
-proc run_client {test tkfile client} {
-    global env
-    global hostname
-    global GSSCLIENT
-    global spawn_id
-    global gss_server_spawn_id
-    global REALMNAME
-    global portbase
-
-    set env(KRB5CCNAME) $tkfile
-    verbose "KRB5CCNAME=$env(KRB5CCNAME)"
-    verbose "spawning gssclient, identity=$client"
-    spawn $GSSCLIENT -d -port [expr 8 + $portbase] $hostname gssservice@$hostname "message from $client"
-    set got_client 0
-    set got_server 0
-    expect_after {
-	-i $spawn_id
-	timeout {
-	    if {!$got_client} {
-		verbose -log "client timeout"
-		fail $test
-		catch "expect_after"
-		return
-	    }
-	}
-	eof {
-	    if {!$got_client} {
-		verbose -log "client eof"
-		fail $test
-		catch "expect_after"
-		return
-	    }
-	}
-	-i $gss_server_spawn_id
-	timeout {
-	    if {!$got_server} {
-		verbose -log "server timeout"
-		fail $test
-		catch "expect_after"
-		return
-	    }
-	}
-	eof {
-	    if {!$got_server} {
-		verbose -log "server eof"
-		fail $test
-		catch "expect_after"
-		return
-	    }
-	}
-    }
-    expect {
-	-i $gss_server_spawn_id
-	"Accepted connection: \"$client@$REALMNAME\"" exp_continue
-	"Received message: \"message from $client\"" {
-	    set got_server 1
-	    if {!$got_client} {
-		exp_continue
-	    }
-	}
-	-i $spawn_id
-	"Signature verified" {
-	    set got_client 1
-	    if {!$got_server} {
-		exp_continue
-	    }
-	}
-    }
-    catch "expect_after"
-    if ![check_exit_status $test] {
-	# check_exit_staus already calls fail for us
-	return
-    }
-    pass $test
-}
-
-proc doit { } {
-    global REALMNAME
-    global env
-    global KLIST
-    global KDESTROY
-    global KEY
-    global GSSTEST
-    global GSSSERVER
-    global GSSCLIENT
-    global hostname
-    global tmppwd
-    global spawn_id
-    global timeout
-    global gss_server_pid
-    global gss_server_spawn_id
-    global gss_save_ccname
-    global gss_save_ktname
-    global portbase
-
-    # Start up the kerberos and kadmind daemons.
-    if ![start_kerberos_daemons 0] {
-	perror "failed to start kerberos daemons"
-    }
-
-    # Use kadmin to add a key for us.
-    if ![add_kerberos_key gsstest0 0] {
-	perror "failed to set up gsstest0 key"
-    }
-
-    # Use kadmin to add a key for us.
-    if ![add_kerberos_key gsstest1 0] {
-	perror "failed to set up gsstest1 key"
-    }
-
-    # Use kadmin to add a key for us.
-    if ![add_kerberos_key gsstest2 0] {
-	perror "failed to set up gsstest2 key"
-    }
-
-    # Use kadmin to add a key for us.
-    if ![add_kerberos_key gsstest3 0] {
-	perror "failed to set up gsstest3 key"
-    }
-
-    # Use kadmin to add a service key for us.
-    if ![add_random_key gssservice/$hostname 0] {
-	perror "failed to set up gssservice/$hostname key"
-    }
-
-    # Use kdb5_edit to create a keytab entry for gssservice
-    if ![setup_keytab 0 gssservice] {
-	perror "failed to set up gssservice keytab"
-    }
-
-    catch "exec rm -f $tmppwd/gss_tk_0 $tmppwd/gss_tk_1 $tmppwd/gss_tk_2 $tmppwd/gss_tk_3"
-
-    # Use kinit to get a ticket.
-    if ![our_kinit gsstest0 gsstest0$KEY $tmppwd/gss_tk_0] {
-	perror "failed to kinit gsstest0"
-    }
-
-    # Use kinit to get a ticket.
-    if ![our_kinit gsstest1 gsstest1$KEY $tmppwd/gss_tk_1] {
-	perror "failed to kinit gsstest1"
-    }
-
-    # Use kinit to get a ticket.
-    if ![our_kinit gsstest2 gsstest2$KEY $tmppwd/gss_tk_2] {
-	perror "failed to kinit gsstest2"
-    }
-
-    # Use kinit to get a ticket.
-    if ![our_kinit gsstest3 gsstest3$KEY $tmppwd/gss_tk_3] {
-	perror "failed to kinit gsstest3"
-    }
-
-    #
-    # Save settings of KRB5CCNAME and KRB5_KTNAME
-    #
-    if [info exists env(KRB5CCNAME)] {
-	set gss_save_ccname $env(KRB5CCNAME)
-    }
-    if [info exists env(KRB5_KTNAME)] {
-	set gss_save_ktname $env(KRB5_KTNAME)
-    }
-
-    #
-    # set KRB5CCNAME and KRB5_KTNAME
-    #
-    set env(KRB5_KTNAME) FILE:$tmppwd/keytab
-    verbose "KRB5_KTNAME=$env(KRB5_KTNAME)"
-
-    # Now start the gss-server.
-    spawn $GSSSERVER -export -logfile $tmppwd/gss-server.log -verbose -port [expr 8 + $portbase] gssservice@$hostname
-    set gss_server_pid [exp_pid]
-    set gss_server_spawn_id $spawn_id
-
-    expect {
-	"starting" { }
-	eof        { perror "gss-server failed to start" }
-    }
-
-    run_client gssclient0 $tmppwd/gss_tk_0 gssclient0
-    run_client gssclient1 $tmppwd/gss_tk_1 gssclient1
-    run_client gssclient2 $tmppwd/gss_tk_2 gssclient2
-    run_client gssclient3 $tmppwd/gss_tk_3 gssclient3
-
-    stop_gss_server
-    gss_restore_env
-
-    if ![our_kdestroy $tmppwd/gss_tk_0] {
-	perror "failed kdestroy gss_tk_0" 0
-    }
-
-    if ![our_kdestroy $tmppwd/gss_tk_1] {
-	perror "failed kdestroy gss_tk_1" 0
-    }
-
-    if ![our_kdestroy $tmppwd/gss_tk_2] {
-	perror "failed kdestroy gss_tk_2" 0
-    }
-
-    if ![our_kdestroy $tmppwd/gss_tk_3] {
-	perror "failed kdestroy gss_tk_3" 0
-    }
-
-    catch "exec rm -f $tmppwd/gss_tk_0 $tmppwd/gss_tk_1 $tmppwd/gss_tk_2 $tmppwd/gss_tk_3"
-
-    return
-}
-
-set status [catch doit msg]
-
-stop_gss_server
-gss_restore_env
-stop_kerberos_daemons
-
-if { $status != 0 } {
-    perror "error in gssapi.exp" 0
-    perror $msg 0
-}
diff --git a/src/tests/dejagnu/krb-standalone/princexpire.exp b/src/tests/dejagnu/krb-standalone/princexpire.exp
deleted file mode 100644
index 5228141..0000000
--- a/src/tests/dejagnu/krb-standalone/princexpire.exp
+++ /dev/null
@@ -1,105 +0,0 @@
-proc doit { } {
-    global REALMNAME
-    global KLIST
-    global KINIT
-    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
-
-    set princ "expiredprinc"
-
-    # Start up the kerberos and kadmind daemons.
-    if ![start_kerberos_daemons 0] {
-	return 1
-    }
-
-    # Use kadmin to add a key.
-    if ![add_kerberos_key $princ 0] {
-	return 1
-    }
-
-    setup_kerberos_env kdc
-
-    set test "kadmin.local modprinc -expire"
-    spawn $KADMIN_LOCAL -q "modprinc -expire \"2 days ago\" $princ"
-    catch expect_after
-    expect {
-	timeout {
-	    fail $test
-	}
-	eof {
-	    pass $test
-	}
-    }
-    set k_stat [wait -i $spawn_id]
-    verbose "wait -i $spawn_id returned $k_stat ($test)"
-    catch "close -i $spawn_id"
-
-    set test "kadmin.local -pwexpire"
-    spawn $KADMIN_LOCAL -q "modprinc -pwexpire \"2 days ago\" $princ"
-    catch expect_after
-    expect {
-	timeout {
-	    fail $test
-	}
-	eof {
-	    pass $test
-	}
-    }
-    set k_stat [wait -i $spawn_id]
-    verbose "wait -i $spawn_id returned $k_stat ($test)"
-    catch "close -i $spawn_id"
-
-    setup_kerberos_env client
-    spawn $KINIT -5 -k -t /dev/null $princ
-    expect {
-	"entry in database has expired" {
-	    pass $test
-	}
-	"Password has expired" {
-	    fail "$test (inappropriate password expiration message)"
-	}
-	timeout {
-	    expect eof
-	    fail "$test (timeout)"
-	    return 0
-	}
-	eof {
-	    fail "$test (eof)"
-	    return 0
-	}
-    }
-    expect eof
-    return 0
-}
-
-run_once princexpire {
-    # 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 not being called from
-    # standalone.exp.
-    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/sample.exp b/src/tests/dejagnu/krb-standalone/sample.exp
deleted file mode 100644
index 93a75f1..0000000
--- a/src/tests/dejagnu/krb-standalone/sample.exp
+++ /dev/null
@@ -1,217 +0,0 @@
-# Test for the sample clients
-# This is a DejaGnu test script.
-# This script tests that sample user-user communication works.
-
-# This mostly just calls procedures in test/dejagnu/config/default.exp.
-
-if ![info exists KLIST] {
-    set KLIST [findfile $objdir/../../clients/klist/klist]
-}
-
-if ![info exists KDESTROY] {
-    set KDESTROY [findfile $objdir/../../clients/kdestroy/kdestroy]
-}
-
-if ![info exists SSERVER] {
-    set SSERVER [findfile $objdir/../../appl/sample/sserver/sserver]
-}
-if ![info exists SCLIENT] {
-    set SCLIENT [findfile $objdir/../../appl/sample/sclient/sclient]
-}
-
-# 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
-}
-
-proc start_sserver_daemon { inetd } {
-    global spawn_id
-    global sserver_pid
-    global sserver_spawn_id
-    global SSERVER
-    global T_INETD
-    global tmppwd
-    global portbase
-
-    # if inetd = 0, then we are running stand-alone
-    if !{$inetd} {
-	    # Start the sserver
-	    spawn $SSERVER -p [expr 8 + $portbase] -S $tmppwd/keytab
-	    set sserver_pid [exp_pid]
-	    set sserver_spawn_id $spawn_id
-
-	    verbose "sserver_spawn is $sserver_spawn_id" 1
-
-	    # Give sserver some time to start
-	    sleep 2
-    } else {
-	    # Start the sserver
-	    spawn $T_INETD [expr 8 + $portbase] $SSERVER sserver -S $tmppwd/keytab
-	    set sserver_pid [exp_pid]
-	    set sserver_spawn_id $spawn_id
-
-	    verbose "sserver_spawn (t_inetd) is $sserver_spawn_id" 1
-
-	    expect {
-		-ex "Ready!"	{ }
-		eof		{ error "couldn't start t_inetd helper" }
-	    }
-    }
-
-    return 1
-}
-
-
-proc stop_sserver_daemon { } {
-    global sserver_pid
-    global sserver_spawn_id
-
-    if [info exists sserver_pid] {
-	catch "close -i $sserver_spawn_id"
-	catch "exec kill $sserver_pid"
-	wait -i $sserver_spawn_id
-	unset sserver_pid
-    }
-
-    return 1
-}
-
-proc stop_check_sserver_daemon { } {
-    global sserver_spawn_id
-    global sserver_pid
-
-    # Check the exit status of sserver - should exit here
-    set status_list [wait -i $sserver_spawn_id]
-    verbose "wait -i $sserver_spawn_id returned $status_list (sserver)"
-    catch "close -i $sserver_spawn_id"
-    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
-	send_log "exit status: $status_list\n"
-	verbose "exit status: $status_list"
-	fail "sserver"
-    } else {
-	pass "sserver"
-    }
-    # In either case the server shutdown
-    unset sserver_pid
-}
-
-proc test_sclient { msg } {
-    global REALMNAME
-    global SCLIENT
-    global hostname
-    global spawn_id
-    global portbase
-
-    # Test the client
-    spawn $SCLIENT $hostname [expr 8 + $portbase]
-    verbose "sclient_spawn is  $spawn_id" 1
-
-    expect {
-	"sendauth succeeded, reply is:" {
-		verbose "Start proper message"
-	}
-	timeout {
-		fail $msg 
-		return 0
-	}
-	eof {
-		fail $msg 
-		return 0
-	}	
-     }
-
-    expect {
-	"You are krbtest/admin@$REALMNAME\r" {
-		verbose "received valid sample message"}
-	eof {
-		fail $msg 
-		return 0
-	    }
-    }
-    # This last expect seems useless, but without it the test hangs on
-    # NETBSD.
-    expect {
-        "\r" { }
-    }
-
-    if ![check_exit_status "ssample"] {
-	return 0
-    }
-
-    return 1
-}
-# 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 doit { } {
-    global hostname
-    global KEY
-    global sserver_pid
-    global sserver_spawn_id
-
-    # Start up the kerberos and kadmind daemons.
-    if ![start_kerberos_daemons 0] {
-	return
-    }
-
-    # Use kadmin to add an host key.
-    if ![add_random_key sample/$hostname 1] {
-	return
-    }
-
-    # Use ksrvutil to create a keytab entry for sample
-    if ![setup_keytab 1 sample] {
-	return
-    }
-
-    # Use kinit to get a ticket.
-    if ![kinit krbtest/admin adminpass$KEY 1] {
-	return
-    }
-
-    run_once sample_standalone {
-	if ![start_sserver_daemon 0 ] {
-	    return 
-	}
-
-	if ![test_sclient sclient] {
-	    return
-	}
-    
-	pass "sample - standalone"
-
-	stop_check_sserver_daemon
-    }
-    
-    if ![start_sserver_daemon 1 ] {
-	return 
-    }
-
-    if ![test_sclient sclient-inetd] {
-	return
-    }
-    
-    pass "sample - inetd"
-
-    stop_check_sserver_daemon
-    return
-}
-
-set status [catch doit msg]
-
-stop_sserver_daemon
-
-stop_kerberos_daemons
-
-if { $status != 0 } {
-    send_error "ERROR: error in sample.exp\n"
-    send_error "$msg\n"
-    exit 1
-}
diff --git a/src/tests/dejagnu/krb-standalone/simple.exp b/src/tests/dejagnu/krb-standalone/simple.exp
deleted file mode 100644
index d8b2182..0000000
--- a/src/tests/dejagnu/krb-standalone/simple.exp
+++ /dev/null
@@ -1,216 +0,0 @@
-# Test for the simple clients
-# This is a DejaGnu test script.
-# This script tests that krb-safe and krb-priv messages work.
-
-# This mostly just calls procedures in test/dejagnu/config/default.exp.
-
-if ![info exists KLIST] {
-    set KLIST [findfile $objdir/../../clients/klist/klist]
-}
-
-if ![info exists KDESTROY] {
-    set KDESTROY [findfile $objdir/../../clients/kdestroy/kdestroy]
-}
-
-if ![info exists SIM_SERVER] {
-    set SIM_SERVER [findfile $objdir/../../appl/simple/server/sim_server]
-}
-if ![info exists SIM_CLIENT] {
-    set SIM_CLIENT [findfile $objdir/../../appl/simple/client/sim_client]
-}
-
-# 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
-}
-
-proc start_sim_server_daemon { } {
-    global spawn_id
-    global sim_server_pid
-    global sim_server_spawn_id
-    global SIM_SERVER
-    global T_INETD
-    global tmppwd
-    global portbase
-
-    # Start the sim_server
-    spawn $SIM_SERVER -p [expr 8 + $portbase] -S $tmppwd/keytab
-    set sim_server_pid [exp_pid]
-    set sim_server_spawn_id $spawn_id
-
-    verbose "sim_server_spawn is $sim_server_spawn_id" 1
-
-    expect {
-	"starting"	{ }
-	eof		{ perror "sim_server failed to start" }
-    }
-
-    return 1
-}
-
-
-proc stop_sim_server_daemon { } {
-    global sim_server_pid
-    global sim_server_spawn_id
-
-    if [info exists sim_server_pid] {
-	catch "close -i $sim_server_spawn_id"
-	catch "exec kill $sim_server_pid"
-	wait -i $sim_server_spawn_id
-	unset sim_server_pid
-    }
-
-    return 1
-}
-
-proc stop_check_sim_server_daemon { } {
-    global sim_server_spawn_id
-    global sim_server_pid
-
-    # Check the exit status of sim_server - should exit here
-    set status_list [wait -i $sim_server_spawn_id]
-    verbose "wait -i $sim_server_spawn_id returned $status_list (sim_server)"
-    catch "close -i $sim_server_spawn_id"
-    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
-	send_log "exit status: $status_list\n"
-	verbose "exit status: $status_list"
-	fail "sim_server"
-    } else {
-	pass "sim_server"
-    }
-    # In either case the server shutdown
-    unset sim_server_pid
-}
-
-proc test_sim_client { msg } {
-    global REALMNAME
-    global SIM_CLIENT
-    global hostname
-    global spawn_id
-    global portbase
-    global sim_server_spawn_id
-
-    # Test the client
-    spawn $SIM_CLIENT -p [expr 8 + $portbase] $hostname
-    verbose "sim_client_spawn is  $spawn_id" 1
-
-    expect {
-	"Sent checksummed message: " {
-		verbose "received safe message"
-	}
-	timeout {
-		fail $msg 
-		return 0
-	}
-	eof {
-		fail $msg 
-		return 0
-	}	
-     }
-
-    expect {
-	"Sent encrypted message: " {
-		verbose "received private message"
-	}
-	eof {
-		fail $msg 
-		return 0
-	    }
-    }
-    expect {
-        "\r" { }
-    }
-
-    expect {
-	-i $sim_server_spawn_id
-	"Safe message is: 'hi there!'" { }
-	timeout {
-	    fail $msg
-	    return 0
-	}
-	eof {
-	    fail $msg
-	    return 0
-	}
-    }
-
-    expect {
-	-i $sim_server_spawn_id
-	"Decrypted message is: 'hi there!'" { }
-	timeout {
-	    fail $msg
-	    return 0
-	}
-	eof {
-	    fail $msg
-	    return 0
-	}
-    }
-
-    if ![check_exit_status "simple"] {
-	return 0
-    }
-
-    return 1
-}
-# 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 doit { } {
-    global hostname
-    global KEY
-    global sim_server_pid
-    global sim_server_spawn_id
-
-    # Start up the kerberos and kadmind daemons.
-    if ![start_kerberos_daemons 0] {
-	return
-    }
-
-    # Use kadmin to add an host key.
-    if ![add_random_key sample/$hostname 1] {
-	return
-    }
-
-    # Use ksrvutil to create a keytab entry for sample
-    if ![setup_keytab 1 sample] {
-	return
-    }
-
-    # Use kinit to get a ticket.
-    if ![kinit krbtest/admin adminpass$KEY 1] {
-	return
-    }
-
-    if ![start_sim_server_daemon] {
-	return 
-    }
-
-    if ![test_sim_client sim_client] {
-	return
-    }
-    
-    pass "simple - standalone"
-
-    stop_check_sim_server_daemon
-    return
-}
-
-set status [catch doit msg]
-
-stop_sim_server_daemon
-
-stop_kerberos_daemons
-
-if { $status != 0 } {
-    send_error "ERROR: error in simple.exp\n"
-    send_error "$msg\n"
-    exit 1
-}
diff --git a/src/tests/dejagnu/krb-standalone/tcp.exp b/src/tests/dejagnu/krb-standalone/tcp.exp
deleted file mode 100644
index df3195b..0000000
--- a/src/tests/dejagnu/krb-standalone/tcp.exp
+++ /dev/null
@@ -1,112 +0,0 @@
-# Standalone Kerberos test.
-# This is a DejaGnu test script.
-# This script tests that the Kerberos tools can talk to each other.
-
-# This mostly just calls procedures in testsuite/config/default.exp.
-
-# 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 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 1] {
-	return
-    }
-
-    # Use kadmin to add an host key.
-    if ![add_random_key host/$hostname 1] {
-	return
-    }
-
-    # Use kinit to get a ticket.
-    if ![kinit krbtest/admin adminpass$KEY 1] {
-	return
-    }
-
-    # Make sure that klist can see the ticket.
-    if ![do_klist "krbtest/admin@$REALMNAME" "krbtgt/$REALMNAME@$REALMNAME" "klist"] {
-	return
-    }
-
-    # Destroy the ticket.
-    spawn $KDESTROY -5
-    if ![check_exit_status "kdestroy"] {
-	return
-    }
-    pass "kdestroy"
-
-    set response {}
-    set got_response 0
-    set kdcsock ""
-    catch {
-	send_log "connecting to $hostname [expr 3 + $portbase]\n"
-	set kdcsock [socket $hostname [expr 3 + $portbase]]
-	fconfigure $kdcsock -encoding binary -blocking 0 -buffering none
-	puts -nonewline $kdcsock [binary format H* ffffffff]
-	# XXX
-	sleep 3
-	set response [read $kdcsock]
-	set got_response 1
-    } msg
-    if [string length $kdcsock] { catch "close $kdcsock" }
-    if $got_response {
-#	send_log [list sent length -1, got back $response]
-#	send_log "\n"
-	if [string length $response]>10 {
-	    pass "too-long TCP request"
-	} else {
-	    send_log "response too short\n"
-	    fail "too-long TCP request"
-	}
-    } else {
-	send_log "too-long connect/exchange failure: $msg\n"
-	fail "too-long TCP request"
-    }
-}
-
-set status 0
-run_once tcp {
-    # Set up the Kerberos files and environment.
-    set mode tcp
-    reset_kerberos_files
-    if {![get_hostname] || ![setup_kerberos_files] || ![setup_kerberos_env]} {
-	set mode udp
-	reset_kerberos_files
-	return
-    }
-    # Reset now, for next time we write the config files.
-    set mode udp
-
-    # Initialize the Kerberos database.  The argument tells
-    # setup_kerberos_db that it is being called from here.
-    if ![setup_kerberos_db 1] {
-	reset_kerberos_files
-	return
-    }
-
-    set status [catch doit msg]
-}
-
-reset_kerberos_files
-stop_kerberos_daemons
-
-if { $status != 0 } {
-    send_error "ERROR: error in standalone.exp\n"
-    send_error "$msg\n"
-    exit 1
-}
diff --git a/src/tests/t_general.py b/src/tests/t_general.py
index 043f751..8e81db1 100755
--- a/src/tests/t_general.py
+++ b/src/tests/t_general.py
@@ -37,6 +37,16 @@ realm.stop()
 
 realm = K5Realm(create_host=False)
 
+# Regression test for #6428 (KDC should prefer account expiration
+# error to password expiration error).
+mark('#6428 regression test')
+realm.run([kadminl, 'addprinc', '-randkey', '-pwexpire', 'yesterday', 'xpr'])
+realm.run(['./icred', 'xpr'], expected_code=1,
+          expected_msg='Password has expired')
+realm.run([kadminl, 'modprinc', '-expire', 'yesterday', 'xpr'])
+realm.run(['./icred', 'xpr'], expected_code=1,
+          expected_msg="Client's entry in database has expired")
+
 # Regression test for #8454 (responder callback isn't used when
 # preauth is not required).
 mark('#8454 regression test')
diff --git a/src/util/k5test.py b/src/util/k5test.py
index c26bc69..e41bf36 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -867,6 +867,13 @@ def stop_daemon(proc):
         _daemons.remove(proc)
 
 
+def await_daemon_exit(proc):
+    code = proc.wait()
+    _daemons.remove(proc)
+    if code != 0:
+        fail('Daemon process %d exited with status %d' % (proc.pid, code))
+
+
 class K5Realm(object):
     """An object representing a functional krb5 test realm."""
 
@@ -1034,7 +1041,7 @@ class K5Realm(object):
             port = self.server_port()
         if env is None:
             env = self.env
-        inetd_args = [t_inetd, str(port)] + args
+        inetd_args = [t_inetd, str(port), args[0]] + args
         return _start_daemon(inetd_args, env, 'Ready!')
 
     def create_kdb(self):
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.