# 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.

# 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 1] {
    return
}

# 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 dump_and_reload {} {
    global KDB5_UTIL
    global tmppwd

    set dumpfile $tmppwd/dump-file
    set dumpokfile $dumpfile.dump_ok

    set test1name "kdb5_util dump"
    set test2name "kdb5_util load"

    if [file exists $dumpfile] { file delete $dumpfile }
    if [file exists $dumpokfile] { file delete $dumpokfile }

    spawn $KDB5_UTIL dump $dumpfile
    expect {
	-re "..*" {
	    fail $test1name
	    untested $test2name
	    return
	}
	timeout {
	    fail $test1name
	    untested $test2name
	    return
	}
	eof { }
    }
    if ![check_exit_status $test1name] {
	untested $test2name
	return
    }
    if ![file exists $dumpfile]||![file exists $dumpokfile] {
	fail $test1name
	untested $test2name
	return
    }
    pass $test1name

    spawn $KDB5_UTIL load $dumpfile
    expect {
	-re "..*" {
	    fail $test2name
	    return
	}
	timeout {
	    fail $test2name
	    return
	}
	eof { }
    }
    if [check_exit_status $test2name] {
	pass $test2name
    }
}

proc kinit_wrong_pw { name badpass } {
    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 distiguish 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 bad pw"
	    return 0
	}
	eof {
	    fail "kinit bad pw"
	    return 0
	}
    }
    send "$badpass\r"
    expect {
	"Password incorrect while getting initial credentials" {
	}
	timeout {
	    fail "kinit bad pw"
	    # kill it?
	}
	eof {
	    fail "kinit bad pw"
	    return
	}
    }
    expect eof

    set status_list [wait -i $spawn_id]
    catch "close -i $spawn_id"
    verbose -log "exit status: $status_list"
    if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
	pass "kinit bad pw"
    } else {
	fail "kinit bad pw"
    }
}

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
    global tmppwd

    setup_kerberos_env kdc

    # 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
    }

    spawn $KADMIN_LOCAL -q "addpol fred"
    catch expect_after
    expect {
	timeout {
	    fail "kadmin.local addpol fred"
	}
	eof {
	    pass "kadmin.local addpol fred"
	}
    }
    set k_stat [wait -i $spawn_id]
    verbose "wait -i $spawn_id returned $k_stat (kadmin addpol)"
    catch "close -i $spawn_id"

    # Use ksrvutil to create a keytab entry.
    if ![setup_keytab 1] {
	return
    }

    # Test dump and load.  Continue on, whatever the result.
    dump_and_reload

    spawn $KADMIN_LOCAL -q "getpols"
    expect {
	fred {
	    pass "kadmin.local getpols"
	    expect eof
	}
	timeout {
	    fail "kadmin.local getpols"
	}
	eof {
	    fail "kadmin.local getpols"
	}
    }
    set k_stat [wait -i $spawn_id]
    verbose "wait -i $spawn_id returned $k_stat (kadmin addpol)"
    catch "close -i $spawn_id"

    # Test use of wrong password.
    kinit_wrong_pw krbtest/admin wrongpassword

    setup_kerberos_env client
    # Use kinit to get a ticket.
    if ![kinit krbtest/admin adminpass$KEY 1] {
	return
    }

    if ![kinit_renew 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
    }

# Get a ticket to later use with FAST
    if ![kinit krbtest/fast adminpass$KEY 1] {
	return
    }

    # Use fast to get a ticket
    if ![kinit_fast krbtest/fast adminpass$KEY 1] {
	return
    }

    # Destroy the ticket.
    spawn $KDESTROY -5
    if ![check_exit_status "kdestroy"] {
	return
    }
    pass "kdestroy"

    # Double check that the ticket was destroyed.
    if ![do_klist_err "klist after destroy"] { return }

    if ![add_random_key WELLKNOWN/ANONYMOUS 0] {
	return
    }

    # If we have anonymous  then test it
    if [file exists "$tmppwd/../../../plugins/preauth/pkinit.so" ] {
	kinit_anonymous "WELLKNOWN/ANONYMOUS"
    }

    if ![add_random_key foo/bar 1] {
	return
    }

    set keytab $tmppwd/fookeytab
    catch "exec rm -f $keytab"

    modify_principal foo/bar -kvno 252
    foreach vno {253 254 255 256 257 258} {
	xst $tmppwd/fookeytab foo/bar
	do_klist_kt $tmppwd/fookeytab "klist keytab foo/bar vno $vno"
	kinit_kt "foo/bar" $tmppwd/fookeytab 1 "kt kvno $vno"
	do_klist "foo/bar" "krbtgt/$REALMNAME@$REALMNAME" "klist kt foo/bar vno $vno"
	do_kdestroy "kdestroy foo/bar vno $vno"
    }
    catch "exec rm -f $keytab"
    # Check that kadmin.local can actually read the correct kvno, even
    # if we don't expect kadmin to be able to.
    setup_kerberos_env kdc
    spawn $KADMIN_LOCAL -r $REALMNAME
    set ok 1
    expect_after {
	timeout		{ fail "kadmin.local correct high kvno" ; set ok 0 }
	eof		{ fail "kadmin.local correct high kvno" ; set ok 0 }
    }
    expect "kadmin.local: "
    send "getprinc foo/bar\r"
#    exec sleep 10
    expect "Key: vno $vno,"
    send "quit\r"
    expect eof
    if [check_exit_status "kadmin.local examine foo/bar for high kvno"] {
	if $ok {
	    pass "kadmin.local correct high kvno"
	}
    }
}

set status [catch doit msg]

stop_kerberos_daemons

if { $status != 0 } {
    send_error "ERROR: error in standalone.exp\n"
    send_error "$msg\n"
    exit 1
}
