svn rev #3259: trunk/ tests/ tests/config/ tests/krb-root/ tests/krb-standalone/ ...
ghudson@MIT.EDU
ghudson at MIT.EDU
Fri Jul 10 16:35:46 EDT 2009
Commit By: ghudson
Log Message:
Add test framework and application tests. Root tests are currently
failing.
Changed Files:
U trunk/Makefile.in
U trunk/aclocal.m4
U trunk/configure.ac
U trunk/pre.in
A trunk/tests/
A trunk/tests/Makefile.in
A trunk/tests/config/
A trunk/tests/config/default.exp
A trunk/tests/deps
A trunk/tests/krb-root/
A trunk/tests/krb-root/rlogin.exp
A trunk/tests/krb-root/telnet.exp
A trunk/tests/krb-standalone/
A trunk/tests/krb-standalone/gssftp.exp
A trunk/tests/krb-standalone/rcp.exp
A trunk/tests/krb-standalone/rsh.exp
A trunk/tests/resolve/
A trunk/tests/resolve/Makefile.in
A trunk/tests/resolve/addrinfo-test.c
A trunk/tests/resolve/deps
A trunk/tests/resolve/fake-addrinfo-test.c
A trunk/tests/resolve/resolve.c
A trunk/tests/t_inetd.c
Modified: trunk/Makefile.in
===================================================================
--- trunk/Makefile.in 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/Makefile.in 2009-07-10 20:35:46 UTC (rev 3259)
@@ -1,6 +1,4 @@
mydir=.
BUILDTOP=$(REL)$(C)
-SUBDIRS= sample simple user_user gss-sample \
- libpty bsd gssftp telnet
-
+SUBDIRS= libpty bsd gssftp telnet tests
Modified: trunk/aclocal.m4
===================================================================
--- trunk/aclocal.m4 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/aclocal.m4 2009-07-10 20:35:46 UTC (rev 3259)
@@ -506,231 +506,6 @@
])dnl
dnl
-dnl AC_KRB5_TCL_FIND_CONFIG (uses tcl_dir)
-dnl
-AC_DEFUN(AC_KRB5_TCL_FIND_CONFIG,[
-AC_REQUIRE([KRB5_LIB_AUX])dnl
-AC_MSG_CHECKING(for tclConfig.sh)
-dnl On Debian, we might be given --with-tcl=/usr, or tclsh might
-dnl point us to /usr/lib/tcl8.4; either way, we need to find
-dnl /usr/lib/tcl8.4/tclConfig.sh.
-dnl On NetBSD, we might be given --with-tcl=/usr/pkg, or tclsh
-dnl might point us to /usr/pkg/lib/tcl8.4; we need to find
-dnl /usr/pkg/lib/tclConfig.sh.
-if test -r "$tcl_dir/lib/tclConfig.sh" ; then
- tcl_conf="$tcl_dir/lib/tclConfig.sh"
-elif test -r "$tcl_dir/tclConfig.sh" ; then
- tcl_conf="$tcl_dir/tclConfig.sh"
-elif test -r "$tcl_dir/../tclConfig.sh" ; then
- tcl_conf="$tcl_dir/../tclConfig.sh"
-else
- tcl_conf=
- lib="$tcl_dir/lib"
- changequote(<<,>>)dnl
- for d in "$lib" "$lib"/tcl7.[0-9] "$lib"/tcl8.[0-9] ; do
- if test -r "$d/tclConfig.sh" ; then
- tcl_conf="$tcl_conf $d/tclConfig.sh"
- fi
- done
- changequote([,])dnl
-fi
-if test -n "$tcl_conf" ; then
- AC_MSG_RESULT($tcl_conf)
-else
- AC_MSG_RESULT(not found)
-fi
-tcl_ok_conf=
-tcl_vers_maj=
-tcl_vers_min=
-old_CPPFLAGS=$CPPFLAGS
-old_LIBS=$LIBS
-old_LDFLAGS=$LDFLAGS
-if test -n "$tcl_conf" ; then
- for file in $tcl_conf ; do
- TCL_MAJOR_VERSION=x ; TCL_MINOR_VERSION=x
- AC_MSG_CHECKING(Tcl info in $file)
- . $file
- v=$TCL_MAJOR_VERSION.$TCL_MINOR_VERSION
- if test -z "$tcl_vers_maj" \
- || test "$tcl_vers_maj" -lt "$TCL_MAJOR_VERSION" \
- || test "$tcl_vers_maj" = "$TCL_MAJOR_VERSION" -a "$tcl_vers_min" -lt "$TCL_MINOR_VERSION" ; then
- for incdir in "$TCL_PREFIX/include/tcl$v" "$TCL_PREFIX/include" ; do
- if test -r "$incdir/tcl.h" -o -r "$incdir/tcl/tcl.h" ; then
- CPPFLAGS="$old_CPPFLAGS -I$incdir"
- break
- fi
- done
- LIBS="$old_LIBS `eval echo x $TCL_LIB_SPEC $TCL_LIBS | sed 's/^x//'`"
- LDFLAGS="$old_LDFLAGS $TCL_LD_FLAGS"
- AC_TRY_LINK( , [Tcl_CreateInterp ();],
- tcl_ok_conf=$file
- tcl_vers_maj=$TCL_MAJOR_VERSION
- tcl_vers_min=$TCL_MINOR_VERSION
- AC_MSG_RESULT($v - working),
- AC_MSG_RESULT($v - compilation failed)
- )
- else
- AC_MSG_RESULT(older version $v)
- fi
- done
-fi
-CPPFLAGS=$old_CPPFLAGS
-LIBS=$old_LIBS
-LDFLAGS=$old_LDFLAGS
-tcl_header=no
-tcl_lib=no
-if test -n "$tcl_ok_conf" ; then
- . $tcl_ok_conf
- TCL_INCLUDES=
- for incdir in "$TCL_PREFIX/include/tcl$v" "$TCL_PREFIX/include" ; do
- if test -r "$incdir/tcl.h" -o -r "$incdir/tcl/tcl.h" ; then
- if test "$incdir" != "/usr/include" ; then
- TCL_INCLUDES=-I$incdir
- fi
- break
- fi
- done
- # Need eval because the first-level expansion could reference
- # variables like ${TCL_DBGX}.
- eval TCL_LIBS='"'$TCL_LIB_SPEC $TCL_LIBS $TCL_DL_LIBS'"'
- TCL_LIBPATH="-L$TCL_EXEC_PREFIX/lib"
- TCL_RPATH=":$TCL_EXEC_PREFIX/lib"
- if test "$DEPLIBEXT" != "$SHLIBEXT" && test -n "$RPATH_FLAG"; then
- TCL_MAYBE_RPATH='$(RPATH_FLAG)'"$TCL_EXEC_PREFIX/lib$RPATH_TAIL"
- else
- TCL_MAYBE_RPATH=
- fi
- CPPFLAGS="$old_CPPFLAGS $TCL_INCLUDES"
- AC_CHECK_HEADER(tcl.h,AC_DEFINE(HAVE_TCL_H,1,[Define if tcl.h is available]) tcl_header=yes)
- if test $tcl_header=no; then
- AC_CHECK_HEADER(tcl/tcl.h,AC_DEFINE(HAVE_TCL_TCL_H,1,[Define if tcl/tcl.h is available]) tcl_header=yes)
- fi
- CPPFLAGS="$old_CPPFLAGS"
- tcl_lib=yes
-else
- # If we read a tclConfig.sh file, it probably set this.
- TCL_LIBS=
-fi
-AC_SUBST(TCL_INCLUDES)
-AC_SUBST(TCL_LIBS)
-AC_SUBST(TCL_LIBPATH)
-AC_SUBST(TCL_RPATH)
-AC_SUBST(TCL_MAYBE_RPATH)
-])dnl
-dnl
-dnl AC_KRB5_TCL_TRYOLD
-dnl attempt to use old search algorithm for locating tcl
-dnl
-AC_DEFUN(AC_KRB5_TCL_TRYOLD, [
-AC_REQUIRE([KRB5_AC_FIND_DLOPEN])
-AC_MSG_WARN([trying old tcl search code])
-if test "$with_tcl" != yes -a "$with_tcl" != no; then
- TCL_INCLUDES=-I$with_tcl/include
- TCL_LIBPATH=-L$with_tcl/lib
- TCL_RPATH=:$with_tcl/lib
-fi
-if test "$with_tcl" != no ; then
- krb5_save_CPPFLAGS="$CPPFLAGS"
- krb5_save_LDFLAGS="$LDFLAGS"
- CPPFLAGS="$CPPFLAGS $TCL_INCLUDES"
- LDFLAGS="$LDFLAGS $TCL_LIBPATH"
- tcl_header=no
- AC_CHECK_HEADER(tcl.h,AC_DEFINE(HAVE_TCL_H,1,[Define if tcl.h found]) tcl_header=yes)
- if test $tcl_header=no; then
- AC_CHECK_HEADER(tcl/tcl.h,AC_DEFINE(HAVE_TCL_TCL_H,1,[Define if tcl/tcl.h found]) tcl_header=yes)
- fi
-
- if test $tcl_header = yes ; then
- tcl_lib=no
-
- if test $tcl_lib = no; then
- AC_CHECK_LIB(tcl8.0, Tcl_CreateCommand,
- TCL_LIBS="$TCL_LIBS -ltcl8.0 -lm $DL_LIB $LIBS"
- tcl_lib=yes,,-lm $DL_LIB)
- fi
- if test $tcl_lib = no; then
- AC_CHECK_LIB(tcl7.6, Tcl_CreateCommand,
- TCL_LIBS="$TCL_LIBS -ltcl7.6 -lm $DL_LIB $LIBS"
- tcl_lib=yes,,-lm $DL_LIB)
- fi
- if test $tcl_lib = no; then
- AC_CHECK_LIB(tcl7.5, Tcl_CreateCommand,
- TCL_LIBS="$TCL_LIBS -ltcl7.5 -lm $DL_LIB $LIBS"
- tcl_lib=yes,,-lm $DL_LIB)
-
- fi
- if test $tcl_lib = no ; then
- AC_CHECK_LIB(tcl, Tcl_CreateCommand,
- TCL_LIBS="$TCL_LIBS -ltcl -lm $DL_LIB $LIBS"
- tcl_lib=yes,,-lm $DL_LIB)
-
- fi
- if test $tcl_lib = no ; then
- AC_MSG_WARN("tcl.h found but not library")
- fi
- else
- AC_MSG_WARN(Could not find Tcl which is needed for the kadm5 tests)
- TCL_LIBS=
- fi
- CPPFLAGS="$krb5_save_CPPFLAGS"
- LDFLAGS="$krb5_save_LDFLAGS"
- AC_SUBST(TCL_INCLUDES)
- AC_SUBST(TCL_LIBS)
- AC_SUBST(TCL_LIBPATH)
- AC_SUBST(TCL_RPATH)
-else
- AC_MSG_RESULT("Not looking for Tcl library")
-fi
-])dnl
-dnl
-dnl AC_KRB5_TCL - determine if the TCL library is present on system
-dnl
-AC_DEFUN(AC_KRB5_TCL,[
-TCL_INCLUDES=
-TCL_LIBPATH=
-TCL_RPATH=
-TCL_LIBS=
-TCL_WITH=
-tcl_dir=
-AC_ARG_WITH(tcl,
-[ --with-tcl=path where Tcl resides], , with_tcl=try)
-if test "$with_tcl" = no ; then
- true
-elif test "$with_tcl" = yes -o "$with_tcl" = try ; then
- tcl_dir=/usr
- if test ! -r /usr/lib/tclConfig.sh; then
- cat >> conftest <<\EOF
-puts "tcl_dir=$tcl_library"
-EOF
- if tclsh conftest >conftest.out 2>/dev/null; then
- if grep tcl_dir= conftest.out >/dev/null 2>&1; then
- t=`sed s/tcl_dir=// conftest.out`
- tcl_dir=$t
- fi
- fi # tclsh ran script okay
- rm -f conftest conftest.out
- fi # no /usr/lib/tclConfig.sh
-else
- tcl_dir=$with_tcl
-fi
-if test "$with_tcl" != no ; then
- AC_KRB5_TCL_FIND_CONFIG
- if test $tcl_lib = no ; then
- if test "$with_tcl" != try ; then
- AC_KRB5_TCL_TRYOLD
- else
- AC_MSG_WARN(Could not find Tcl which is needed for some tests)
- fi
- fi
-fi
-# If "yes" or pathname, error out if not found.
-if test "$with_tcl" != no -a "$with_tcl" != try ; then
- if test "$tcl_header $tcl_lib" != "yes yes" ; then
- AC_MSG_ERROR(Could not find Tcl)
- fi
-fi
-])dnl
-dnl
dnl Check if we need the prototype for a function - we give it a bogus
dnl prototype and if it complains - then a valid prototype exists on the
dnl system.
@@ -802,43 +577,6 @@
AC_DEFINE_UNQUOTED([GETSOCKNAME_ARG3_TYPE],$res2,[Type of pointer target for argument 3 to getsockname])
])dnl
dnl
-dnl KRB5_AC_PRIOCNTL_HACK
-dnl
-dnl
-AC_DEFUN([KRB5_AC_PRIOCNTL_HACK],
-[AC_REQUIRE([AC_PROG_AWK])dnl
-AC_REQUIRE([AC_LANG_COMPILER_REQUIRE])dnl
-AC_CACHE_CHECK([whether to use priocntl hack], [krb5_cv_priocntl_hack],
-[case $krb5_cv_host in
-*-*-solaris2.9*)
- if test "$cross_compiling" = yes; then
- krb5_cv_priocntl_hack=yes
- else
- # Solaris patch 117171-11 (sparc) or 117172-11 (x86)
- # fixes the Solaris 9 bug where final pty output
- # gets lost on close.
- if showrev -p | $AWK 'BEGIN { e = 1 }
-/Patch: 11717[[12]]/ { x = index[]([$]2, "-");
-if (substr[]([$]2, x + 1, length([$]2) - x) >= 11)
-{ e = 0 } else { e = 1 } }
-END { exit e; }'; then
- krb5_cv_priocntl_hack=no
- else
- krb5_cv_priocntl_hack=yes
- fi
- fi
- ;;
-*)
- krb5_cv_priocntl_hack=no
- ;;
-esac])
-if test "$krb5_cv_priocntl_hack" = yes; then
- PRIOCNTL_HACK=1
-else
- PRIOCNTL_HACK=0
-fi
-AC_SUBST(PRIOCNTL_HACK)])dnl
-dnl
dnl KRB5_AC_LIBUTIL
dnl
dnl Check for libutil, for NetBSD, et al.; needed for openpty() and
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/configure.ac 2009-07-10 20:35:46 UTC (rev 3259)
@@ -21,9 +21,13 @@
KRB5_CFLAGS=`$krb5_config --cflags`
KRB5_BASE_LIBS=`$krb5_config --libs krb5`" -lkrb5support"
GSS_LIBS=`$krb5_config --libs gssapi`" -lkrb5support"
+KRB5_BINDIR=`$krb5_config --exec-prefix`/bin
+KRB5_SBINDIR=`$krb5_config --exec-prefix`/sbin
AC_SUBST(KRB5_CFLAGS)
AC_SUBST(KRB5_BASE_LIBS)
AC_SUBST(GSS_LIBS)
+AC_SUBST(KRB5_BINDIR)
+AC_SUBST(KRB5_SBINDIR)
WITH_CC
if test -z "$LD" ; then LD=$CC; fi
@@ -40,6 +44,7 @@
AC_CHECK_PROG(AR, ar, ar, false)
AC_FUNC_FORK
AC_TYPE_MODE_T
+AC_TYPE_SIGNAL
AC_CHECK_TYPES([socklen_t, struct sockaddr_storage],,,
[#include <sys/types.h>
#include <sys/socket.h>
@@ -64,9 +69,9 @@
AC_CHECK_HEADERS(curses.h lastlog.h libutil.h memory.h paths.h pty.h stdlib.h)
AC_CHECK_HEADERS(string.h ttyent.h util.h sac.h unistd.h utmp.h utmpx.h)
AC_CHECK_HEADERS(arpa/inet.h arpa/nameser.h)
-AC_CHECK_HEADERS(sys/filio.h sys/ioctl_compat.h sys/label.h sys/select.h)
-AC_CHECK_HEADERS(sys/sockio.h sys/stream.h sys/time.h sys/tty.h sys/uio.h)
-AC_CHECK_HEADERS(sys/utsname.h sys/wait.h)
+AC_CHECK_HEADERS(sys/filio.h sys/ioctl_compat.h sys/label.h sys/param.h)
+AC_CHECK_HEADERS(sys/select.h sys/sockio.h sys/stream.h sys/time.h sys/tty.h)
+AC_CHECK_HEADERS(sys/uio.h sys/utsname.h sys/wait.h)
dnl On some systems, term.h requires curses.h inclusion
AC_CHECK_HEADERS(term.h,,,
[#ifdef HAVE_CURSES_H
@@ -475,6 +480,16 @@
[Define if system termios interface doesn't define speed_t])
fi
+dnl For dejagnu tests
+AC_CHECK_PROG(RUNTEST,runtest,runtest)
+if test x"$RUNTEST" != x; then
+ HAVE_RUNTEST=yes
+else
+ HAVE_RUNTEST=no
+fi
+AC_SUBST(HAVE_RUNTEST)
+
V5_AC_OUTPUT_MAKEFILE(. bsd libpty
gssftp gssftp/ftp gssftp/ftpd
- telnet telnet/libtelnet telnet/telnet telnet/telnetd)
+ telnet telnet/libtelnet telnet/telnet telnet/telnetd
+ tests tests/resolve)
Modified: trunk/pre.in
===================================================================
--- trunk/pre.in 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/pre.in 2009-07-10 20:35:46 UTC (rev 3259)
@@ -169,12 +169,7 @@
CLIENT_MANDIR = $(KRB5MANROOT)/man1
# Dejagnu variables.
-# We have to set the host with --host so that setup_xfail will work.
-# If we don't set it, then the host type used is "native", which
-# doesn't match "*-*-*".
-host=@krb5_cv_host@
-DEJAFLAGS = $(DEJALFLAGS) $(CLFLAGS) --debug --srcdir $(srcdir) --host \
- $(host)
+DEJAFLAGS = --debug --srcdir $(srcdir)
RUNTEST = runtest $(DEJAFLAGS)
transform = @program_transform_name@
Added: trunk/tests/Makefile.in
===================================================================
--- trunk/tests/Makefile.in 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/Makefile.in 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,37 @@
+mydir=tests
+BUILDTOP=$(REL)..
+SUBDIRS = resolve
+
+RUNTEST = @RUNTEST@ $(DEJAFLAGS)
+RUNTESTFLAGS =
+
+SRCS=$(srcdir)/t_inetd.c
+OBJS=t_inetd.o
+
+KRB5_BINDIR = @KRB5_BINDIR@
+KRB5_SBINDIR = @KRB5_SBINDIR@
+
+all install::
+
+check:: check-runtest- at HAVE_RUNTEST@
+
+check-runtest-no::
+ @echo "+++"
+ @echo "+++ WARNING: tests/dejagnu tests not run."
+ @echo "+++ runtest is unavailable."
+ @echo "+++"
+
+# Set VALGRIND at run time, that may be changed when running 'make'.
+check-runtest-yes:: t_inetd site.exp
+ $(RUNTEST) --tool krb VALGRIND="$(VALGRIND)" $(RUNTESTFLAGS)
+
+# KRB5_BASE_LIBS is a cheap way to get network libraries here.
+t_inetd:: t_inetd.o
+ $(CC_LINK) -o t_inetd t_inetd.o $(KRB5_BASE_LIBS)
+
+clean::
+ $(RM) t_inetd tmpdir dbg.log krb.log krb.sum
+
+site.exp: Makefile
+ echo "set KRB5_BINDIR {$(KRB5_BINDIR)}" > site.exp
+ echo "set KRB5_SBINDIR {$(KRB5_SBINDIR)}" >> site.exp
Added: trunk/tests/config/default.exp
===================================================================
--- trunk/tests/config/default.exp 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/config/default.exp 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,2561 @@
+# Basic expect script for Kerberos tests.
+# This is a DejaGnu test script.
+# Written by Ian Lance Taylor, Cygnus Support, <ian at cygnus.com>.
+# This script is automatically run by DejaGnu before running any of
+# the Kerberos test scripts.
+
+# This file provides several functions which deal with a local
+# Kerberos database. We have to do this such that we don't interfere
+# with any existing Kerberos database. We will create all the files
+# in the directory $tmppwd, which will have been created by the
+# testsuite default script. We will use $REALMNAME as our Kerberos
+# realm name, defaulting to KRBTEST.COM.
+
+set timeout 100
+set stty_init {erase \^h kill \^u}
+set env(TERM) dumb
+
+set des3_krbtgt 0
+set tgt_support_desmd5 0
+set supported_enctypes "des-cbc-crc:normal"
+set kdc_supported_enctypes "des-cbc-crc:normal"
+
+# The names of the individual passes must be unique; lots of things
+# depend on it. The PASSES variable may not contain comments; only
+# small pieces get evaluated, so comments will do strange things.
+
+# Most of the purpose of using multiple passes is to exercise the
+# dependency of various bugs on configuration file settings,
+# particularly with regards to encryption types.
+
+# The des.no-kdc-md5 pass will fail if the KDC does not constrain
+# session key enctypes to those in its permitted_enctypes list. It
+# works by assuming enctype similarity, thus allowing the client to
+# request a des-cbc-md4 session key. Since only des-cbc-crc is in the
+# KDC's permitted_enctypes list, the TGT will be unusable.
+
+# KLUDGE for tracking down leaking ptys
+if 0 {
+ rename spawn oldspawn
+ rename wait oldwait
+ proc spawn { args } {
+ upvar 1 spawn_id spawn_id
+ verbose "spawn: args=$args"
+ set pid [eval oldspawn $args]
+ verbose "spawn: pid=$pid spawn_id=$spawn_id"
+ return $pid
+ }
+ proc wait { args } {
+ upvar 1 spawn_id spawn_id
+ verbose "wait: args=$args"
+ set ret [eval oldwait $args]
+ verbose "wait: $ret"
+ return $ret
+ }
+}
+
+if { [string length $VALGRIND] } {
+ rename spawn valgrind_aux_spawn
+ proc spawn { args } {
+ global VALGRIND
+ upvar 1 spawn_id spawn_id
+ set newargs {}
+ set inflags 1
+ set eatnext 0
+ foreach arg $args {
+ if { $arg == "-ignore" \
+ || $arg == "-open" \
+ || $arg == "-leaveopen" } {
+ lappend newargs $arg
+ set eatnext 1
+ continue
+ }
+ if [string match "-*" $arg] {
+ lappend newargs $arg
+ continue
+ }
+ if { $eatnext } {
+ set eatnext 0
+ lappend newargs $arg
+ continue
+ }
+ if { $inflags } {
+ set inflags 0
+ # Only run valgrind for local programs, not
+ # system ones.
+#&&![string match "/bin/sh" $arg] sh is used to start kadmind!
+ if [string match "/" [string index $arg 0]]&&![string match "/bin/ls" $arg]&&![regexp {/kshd$} $arg] {
+ set newargs [concat $newargs $VALGRIND]
+ }
+ }
+ lappend newargs $arg
+ }
+ set pid [eval valgrind_aux_spawn $newargs]
+ return $pid
+ }
+}
+
+# The des.des3-tgt.no-kdc-des3 pass will fail if the KDC doesn't
+# constrain ticket key enctypes to those in permitted_enctypes. It
+# does this by not putting des3 in the permitted_enctypes, while
+# creating a TGT princpal that has a des3 key as well as a des key.
+
+# XXX -- master_key_type is fragile w.r.t. permitted_enctypes; it is
+# possible to configure things such that you have a master_key_type
+# that is not permitted, and the error message used to be cryptic.
+
+set passes {
+ {
+ des
+ mode=udp
+ des3_krbtgt=0
+ {supported_enctypes=des-cbc-crc:normal}
+ {kdc_supported_enctypes=des-cbc-crc:normal}
+ {dummy=[verbose -log "DES TGT, DES enctype"]}
+ }
+ {
+ des.des3tgt
+ mode=udp
+ des3_krbtgt=1
+ {supported_enctypes=des-cbc-crc:normal}
+ {kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+ {dummy=[verbose -log "DES3 TGT, DES enctype"]}
+ }
+ {
+ des3
+ mode=udp
+ des3_krbtgt=1
+ {supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+ {kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+ {dummy=[verbose -log "DES3 TGT, DES3 + DES enctypes"]}
+ }
+ {
+ aes
+ mode=udp
+ des3_krbtgt=0
+ {supported_enctypes=aes256-cts-hmac-sha1-96:normal des-cbc-crc:normal}
+ {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des-cbc-crc:normal}
+ {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des-cbc-crc}
+ {permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des-cbc-crc}
+ {permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des-cbc-crc}
+ {master_key_type=aes256-cts-hmac-sha1-96}
+ {dummy=[verbose -log "AES + DES enctypes"]}
+ }
+ {
+ aes-des3
+ mode=udp
+ des3_krbtgt=0
+ {supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
+ {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
+ {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+ {permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+ {permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+ {master_key_type=aes256-cts-hmac-sha1-96}
+ {dummy=[verbose -log "AES + DES enctypes"]}
+ }
+ {
+ des3-aes
+ mode=udp
+ des3_krbtgt=1
+ {supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
+ {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
+ {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+ {permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+ {permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
+ {master_key_type=aes256-cts-hmac-sha1-96}
+ {dummy=[verbose -log "AES + DES enctypes, DES3 TGT"]}
+ }
+ {
+ des-v4
+ mode=udp
+ des3_krbtgt=0
+ {supported_enctypes=des-cbc-crc:v4}
+ {kdc_supported_enctypes=des-cbc-crc:v4}
+ {default_tkt_enctypes(client)=des-cbc-crc}
+ {dummy=[verbose -log "DES TGT, DES-CRC enctype, V4 salt"]}
+ }
+ {
+ des-md5-v4
+ mode=udp
+ des3_krbtgt=0
+ {supported_enctypes=des-cbc-md5:v4 des-cbc-crc:v4}
+ {kdc_supported_enctypes=des-cbc-md5:v4 des-cbc-crc:v4}
+ {default_tkt_enctypes(client)=des-cbc-md5 des-cbc-crc}
+ {dummy=[verbose -log "DES TGT, DES-MD5 and -CRC enctypes, V4 salt"]}
+ }
+ {
+ all-des-des3-enctypes
+ mode=udp
+ des3_krbtgt=1
+ {supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal \
+ des-cbc-md5:normal des-cbc-crc:v4 des-cbc-md5:norealm \
+ des-cbc-md4:normal}
+ {kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal \
+ des-cbc-md5:normal des-cbc-crc:v4 des-cbc-md5:norealm \
+ des-cbc-md4:normal}
+ {dummy=[verbose -log "DES3 TGT, many DES3 + DES enctypes"]}
+ }
+ {
+ des.no-kdc-md5
+ mode=udp
+ des3_krbtgt=0
+ tgt_support_desmd5=0
+ {permitted_enctypes(kdc)=des-cbc-crc}
+ {default_tgs_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
+ {default_tkt_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
+ {supported_enctypes=des-cbc-crc:normal}
+ {kdc_supported_enctypes=des-cbc-crc:normal}
+ {master_key_type=des-cbc-crc}
+ {dummy=[verbose -log \
+ "DES TGT, KDC permitting only des-cbc-crc"]}
+ }
+ {
+ des.des3-tgt.no-kdc-des3
+ mode=udp
+ tgt_support_desmd5=0
+ {permitted_enctypes(kdc)=des-cbc-crc}
+ {default_tgs_enctypes(client)=des-cbc-crc}
+ {default_tkt_enctypes(client)=des-cbc-crc}
+ {supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+ {kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
+ {master_key_type=des-cbc-crc}
+ {dummy=[verbose -log \
+ "DES3 TGT, KDC permitting only des-cbc-crc"]}
+ }
+}
+
+# des.md5-tgt is set as unused, since it won't trigger the error case
+# if SUPPORT_DESMD5 isn't honored.
+
+# The des.md5-tgt pass will fail if enctype similarity is inconsisent;
+# between 1.0.x and 1.1, the decrypt functions became more strict
+# about matching enctypes, while the KDB retrieval functions didn't
+# coerce the enctype to match what was requested. It works by setting
+# SUPPORT_DESMD5 on the TGT principal, forcing an enctype of
+# des-cbc-md5 on the TGT key. Since the database only contains a
+# des-cbc-crc key, the decrypt will fail if enctypes are not coerced.
+
+# des.no-kdc-md5.client-md4-skey is retained in unsed_passes, even
+# though des.no-kdc-md5 is roughly equivalent, since the associated
+# comment needs additional investigation at some point re the kadmin
+# client.
+
+# The des.no-kdc-md5.client-md4-skey will fail on TGS requests due to
+# the KDC issuing session keys that it won't accept. It will also
+# fail for a kadmin client, but for different reasons, since the kadm5
+# library does some curious filtering of enctypes, and also uses
+# get_in_tkt() rather than get_init_creds(); the former does an
+# intersection of the enctypes provided by the caller and those listed
+# in the config file!
+
+set unused_passes {
+ {
+ des.md5-tgt
+ des3_krbtgt=0
+ tgt_support_desmd5=1
+ supported_enctypes=des-cbc-crc:normal
+ kdc_supported_enctypes=des-cbc-crc:normal
+ {permitted_enctypes(kdc)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
+ {permitted_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
+ {dummy=[verbose -log "DES TGT, SUPPORTS_DESMD5"]}
+ }
+ {
+ des.md5-tgt.no-kdc-md5
+ des3_krbtgt=0
+ tgt_support_desmd5=1
+ {permitted_enctypes(kdc)=des-cbc-crc}
+ {default_tgs_enctypes(client)=des-cbc-crc}
+ {default_tkt_enctypes(client)=des-cbc-crc}
+ {supported_enctypes=des-cbc-crc:normal}
+ {kdc_supported_enctypes=des-cbc-crc:normal}
+ {master_key_type=des-cbc-crc}
+ {dummy=[verbose -log \
+ "DES TGT, SUPPORTS_DESMD5, KDC permitting only des-cbc-crc"]}
+ }
+ {
+ des.no-kdc-md5.client-md4-skey
+ des3_krbtgt=0
+ {permitted_enctypes(kdc)=des-cbc-crc}
+ {permitted_enctypes(client)=des-cbc-crc des-cbc-md4}
+ {default_tgs_enctypes(client)=des-cbc-crc des-cbc-md4}
+ {default_tkt_enctypes(client)=des-cbc-md4}
+ {supported_enctypes=des-cbc-crc:normal}
+ {kdc_supported_enctypes=des-cbc-crc:normal}
+ {dummy=[verbose -log \
+ "DES TGT, DES enctype, KDC permitting only des-cbc-crc, client requests des-cbc-md4 session key"]}
+ }
+ {
+ all-enctypes
+ des3_krbtgt=1
+ {supported_enctypes=\
+ aes256-cts-hmac-sha1-96:normal aes256-cts-hmac-sha1-96:norealm \
+ aes128-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:norealm \
+ des3-cbc-sha1:normal des3-cbc-sha1:none \
+ des-cbc-md5:normal des-cbc-md4:normal des-cbc-crc:normal \
+ des-cbc-md5:v4 des-cbc-md4:v4 des-cbc-crc:v4 \
+ }
+ {kdc_supported_enctypes=\
+ des3-cbc-sha1:normal des3-cbc-sha1:none \
+ des-cbc-md5:normal des-cbc-md4:normal des-cbc-crc:normal \
+ des-cbc-md5:v4 des-cbc-md4:v4 des-cbc-crc:v4 \
+ }
+ {dummy=[verbose -log "DES3 TGT, default enctypes"]}
+ }
+ {
+ aes-tcp
+ mode=tcp
+ des3_krbtgt=0
+ {supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+ {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+ {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
+ {permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
+ {permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
+ {master_key_type=aes256-cts-hmac-sha1-96}
+ {dummy=[verbose -log "AES via TCP"]}
+ }
+}
+# {supported_enctypes=des-cbc-md5:normal des-cbc-crc:normal twofish256-hmac-sha1:normal }
+# {kdc_supported_enctypes= des-cbc-md5:normal des-cbc-crc:normal twofish256-hmac-sha1:normal}
+
+# This shouldn't be necessary on dejagnu-1.4 and later, but 1.3 seems
+# to need it because its runtest.exp doesn't deal with PASS at all.
+if [info exists PASS] {
+ foreach pass $passes {
+ if { [lsearch -exact $PASS [lindex $pass 0]] >= 0 } {
+ lappend MULTIPASS $pass
+ }
+ }
+} else {
+ set MULTIPASS $passes
+}
+
+set last_passname_conf ""
+set last_passname_db ""
+
+# We do everything in a temporary directory.
+if ![info exists TMPDIR] {
+ set tmppwd "[pwd]/tmpdir"
+ if ![file isdirectory $tmppwd] {
+ catch "exec mkdir $tmppwd" status
+ }
+} else {
+ set tmppwd $TMPDIR
+}
+verbose "tmppwd=$tmppwd"
+
+# On Ultrix, use /bin/sh5 in preference to /bin/sh.
+if ![info exists BINSH] {
+ if [file exists /bin/sh5] {
+ set BINSH /bin/sh5
+ } else {
+ set BINSH /bin/sh
+ }
+}
+
+# For security, we must not use generally known passwords. This is
+# because some of the tests may be run as root. If the passwords were
+# generally know, then somebody could work out the appropriate
+# Kerberos ticket to use, and come in when, say, the telnetd daemon
+# was being tested by root. The window for doing this is very very
+# small, so the password does not have to be perfect, it just can't be
+# constant.
+if ![info exists KEY] {
+ catch {exec $BINSH -c "echo $$"} KEY
+ verbose "KEY is $KEY"
+ set keyfile [open $tmppwd/KEY w]
+ puts $keyfile "$KEY"
+ close $keyfile
+}
+
+# Clear away any files left over from a previous run.
+# We can't use them now because we don't know the right KEY.
+# krb5.conf might change if running tests on another host
+file delete $tmppwd/krb5.conf $tmppwd/kdc.conf $tmppwd/slave.conf \
+ $tmppwd/krb5.client.conf $tmppwd/krb5.server.conf \
+ $tmppwd/krb5.kdc.conf $tmppwd/krb5.slave.conf
+
+proc delete_db {} {
+ global tmppwd
+ # Master and slave db files
+ file delete $tmppwd/kdc-db $tmppwd/kdc-db.ok $tmppwd/kdc-db.kadm5 \
+ $tmppwd/kdc-db.kadm5.lock \
+ $tmppwd/kdc-db.ulog \
+ $tmppwd/slave-db $tmppwd/slave-db.ok $tmppwd/slave-db.kadm5 $tmppwd/slave-db.kadm5.lock \
+ $tmppwd/slave-db~ $tmppwd/slave-db~.ok $tmppwd/slave-db~.kadm5 $tmppwd/slave-db~.kadm5.lock
+ # Creating a new database means we need a new srvtab.
+ file delete $tmppwd/srvtab $tmppwd/cpw_srvtab
+}
+
+delete_db
+
+# Put the installed kerberos directories on PATH.
+# This needs to be fixed for V5.
+# set env(PATH) $env(PATH):/usr/kerberos/bin:/usr/kerberos/etc
+# verbose "PATH=$env(PATH)"
+
+# Some of the tests expect $env(USER) to be set.
+if ![info exists env(USER)] {
+ if [info exists env(LOGNAME)] {
+ set env(USER) $env(LOGNAME)
+ } else {
+ if [info exists logname] {
+ set env(USER) $logname
+ } else {
+ catch "exec whoami" env(USER)
+ }
+ }
+}
+
+# set the realm. The user can override this on the runtest line.
+if ![info exists REALMNAME] {
+ set REALMNAME "KRBTEST.COM"
+}
+verbose "Test realm is $REALMNAME"
+
+# Find some programs we need. We use the binaries from the build tree
+# if they exist. If they do not, then they must be in PATH. We
+# expect $objdir to be ...tests/dejagnu.
+
+foreach i {
+ {KDB5_UTIL $KRB5_SBINDIR/kdb5_util}
+ {KRB5KDC $KRB5_SBINDIR/krb5kdc}
+ {KADMIND $KRB5_SBINDIR/kadmind}
+ {KADMIN $KRB5_BINDIR/kadmin}
+ {KADMIN_LOCAL $KRB5_SBINDIR/kadmin.local}
+ {KINIT $KRB5_BINDIR/kinit}
+ {KTUTIL $KRB5_BINDIR/ktutil}
+ {KLIST $KRB5_BINDIR/klist}
+ {KDESTROY $KRB5_BINDIR/kdestroy}
+ {RESOLVE $objdir/resolve/resolve}
+ {T_INETD $objdir/t_inetd}
+} {
+ set varname [lindex $i 0]
+ if ![info exists $varname] {
+ eval set varval [lindex $i 1]
+ set varval [findfile $varval]
+ set $varname $varval
+ verbose "$varname=$varval"
+ } {
+ eval set varval \$$varname
+ verbose "$varname already set to $varval"
+ }
+}
+
+if ![info exists RLOGIN] {
+ set RLOGIN rlogin
+}
+
+if ![info exists RLOGIN_FLAGS] {
+ set RLOGIN_FLAGS "-x"
+}
+
+# We use a couple of variables to hold shell prompts which may be
+# overridden by the user.
+
+if ![info exists ROOT_PROMPT] {
+ set ROOT_PROMPT "(%|#|>|\\$) $"
+}
+
+if ![info exists SHELL_PROMPT] {
+ set SHELL_PROMPT "(%|#|>|\\$) $"
+}
+
+verbose "setting up onexit handler (old handler=[exit -onexit])"
+exit -onexit [concat {
+ verbose "calling stop_kerberos_daemons (onexit handler)"
+ stop_kerberos_daemons;
+} [exit -onexit]]
+
+# run_once
+
+# Many tests are independent of the actual enctypes used, which is
+# what our passes are (currently) all about. Use this to prevent
+# multiple invocations. If a test depends on, say, the master key
+# type but nothing else, you could also use the master key type in the
+# tag name, and avoid redundant tests in additional passes using the
+# same master key type.
+
+proc run_once { tag body } {
+ global run_once_tags
+ if ![info exists run_once_tags($tag)] {
+ set run_once_tags($tag) 1
+ uplevel 1 $body
+ }
+}
+
+# check_k5login
+
+# Most of the tests won't work if the user has a .k5login file, unless
+# the user's name appears with $REALMNAME in .k5login
+
+# This procedure returns 1 if the .k5login file appears to be OK, 0
+# otherwise. This check is not foolproof.
+
+# Note that this previously checked for a username with no realm; this
+# works for krb4's kuserok() but not for krb5_kuserok(), due to some
+# implementation details. *sigh*
+
+proc check_k5login { testname } {
+ global env
+ global REALMNAME
+
+ if {![file exists ~/.k5login]} {
+ if {$env(USER) == "root"} {
+ return 0
+ } else {
+ return 1
+ }
+ }
+
+ verbose "looking for $env(USER)@$REALMNAME in ~/.k5login" 2
+ set file [open ~/.k5login r]
+ while { [gets $file principal] != -1 } {
+ verbose " found $principal" 2
+ if { $principal == "$env(USER)@$REALMNAME" } {
+ close $file
+ return 1
+ }
+ }
+ close $file
+
+ note "$testname test requires that your name appear in your ~/.k5login"
+ note "file in the form $env(USER)@$REALMNAME"
+ unsupported "$testname"
+
+ return 0
+}
+
+proc check_klogin { testname } {
+ global env
+ global REALMNAME
+
+ if {![file exists ~/.klogin]} {
+ if {$env(USER) == "root"} {
+ return 0
+ } else {
+ return 1
+ }
+ }
+
+ verbose "looking for $env(USER) in ~/.klogin" 2
+ set file [open ~/.klogin r]
+ while { [gets $file principal] != -1 } {
+ verbose " found $principal" 2
+ if { $principal == "$env(USER)" \
+ || $principal == "$env(USER)@$REALMNAME" } {
+ close $file
+ return 1
+ }
+ }
+ close $file
+
+ note "$testname test requires that your name appear in your ~/.klogin"
+ note "file without a realm."
+ unsupported "$testname"
+
+ return 0
+}
+
+# check_exit_status
+# Check the exit status of a spawned program (using the caller's value
+# of spawn_id). Returns 1 if the program succeeded, 0 if it failed.
+
+proc check_exit_status { testname } {
+ upvar 1 spawn_id spawn_id
+
+ verbose "about to wait ($testname)"
+ set status_list [wait -i $spawn_id]
+ verbose "wait -i $spawn_id returned $status_list ($testname)"
+ catch "close -i $spawn_id"
+ if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
+ verbose -log "exit status: $status_list"
+ fail "$testname"
+ return 0
+ } else {
+ return 1
+ }
+}
+
+#
+# ENVSTACK
+#
+
+# These procedures implement an environment variable stack. They use
+# the global variable $envvars_tosave for the purpose of identifying
+# which environment variables to save. They also track which ones are
+# unset at any particular point. The stack pointer is $envstackp,
+# which is an integer. The arrays $envstack$envstackp and
+# $unenvstack$envstackp store respectively the set of old environment
+# variables/values pushed onto the stack and the set of old unset
+# environment variables for a given value of $envstackp.
+
+# Changing the value of $envvars_tosave after performing the first
+# push operation may result in strangeness.
+
+#
+# envstack_push
+#
+# Push set of current environment variables.
+#
+proc envstack_push { } {
+ global env
+ global envvars_tosave
+ global envstackp
+ global envstack$envstackp
+ global unenvstack$envstackp
+
+ verbose "envstack_push: starting, sp=$envstackp"
+ foreach i $envvars_tosave {
+ if [info exists env($i)] {
+ verbose "envstack_push: saving $i=$env($i)"
+ set envstack${envstackp}($i) $env($i)
+ } {
+ verbose "envstack_push: marking $i as unset"
+ set unenvstack${envstackp}($i) unset
+ }
+ }
+ incr envstackp
+ verbose "envstack_push: exiting, sp=$envstackp"
+}
+
+#
+# envstack_pop
+#
+# Pop set of current environment variables.
+#
+proc envstack_pop { } {
+ global env
+ global envstackp
+
+ verbose "envstack_pop: starting, sp=$envstackp"
+ incr envstackp -1
+ global envstack$envstackp # YUCK!!! no obvious better way though...
+ global unenvstack$envstackp
+ if {$envstackp < 0} {
+ perror "envstack_pop: stack underflow!"
+ return
+ }
+ if [info exists envstack$envstackp] {
+ foreach i [array names envstack$envstackp] {
+ if [info exists env($i)] {
+ verbose "envstack_pop: $i was $env($i)"
+ }
+ eval set env($i) \$envstack${envstackp}($i)
+ verbose "envstack_pop: restored $i to $env($i)"
+ }
+ unset envstack$envstackp
+ }
+ if [info exists unenvstack$envstackp] {
+ foreach i [array names unenvstack$envstackp] {
+ if [info exists env($i)] {
+ verbose "envstack_pop: $i was $env($i)"
+ unset env($i)
+ verbose "envstack_pop: $i unset"
+ } {
+ verbose "envstack_pop: ignoring already unset $i"
+ }
+ }
+ unset unenvstack$envstackp
+ }
+ verbose "envstack_pop: exiting, sp=$envstackp"
+}
+
+#
+# Initialize the envstack
+#
+set envvars_tosave {
+ KRB5_CONFIG KRB5CCNAME KRBTKFILE KRB5RCACHEDIR
+ KERBEROS_SERVER KRB5_KDC_PROFILE
+}
+set envstackp 0
+envstack_push
+
+# get_hostname
+# This procedure will get the local hostname. It sets the global
+# variables hostname (the full name) and localhostname (the first part
+# of the name). Returns 1 on success, 0 on failure.
+
+proc get_hostname { } {
+ global RESOLVE
+ global hostname
+ global localhostname
+ global domain
+ global tmppwd
+
+ if {[info exists hostname] && [info exists localhostname]} {
+ return 1
+ }
+
+ envstack_push
+ catch "exec $RESOLVE -q >$tmppwd/hostname" exec_output
+ envstack_pop
+ if ![string match "" $exec_output] {
+ verbose -log $exec_output
+ perror "can't get hostname"
+ return 0
+ }
+ set file [open $tmppwd/hostname r]
+ if { [ gets $file hostname ] == -1 } {
+ perror "no output from hostname"
+ return 0
+ }
+ close $file
+ file delete $tmppwd/hostname
+ regexp "^(\[^.\]*)\\.(.*)$" $hostname foo localhostname domain
+
+ set hostname [string tolower $hostname]
+ set localhostname [string tolower $localhostname]
+ set domain [string tolower $domain]
+ verbose "hostname: $hostname; localhostname: $localhostname; domain $domain"
+
+ return 1
+}
+
+# modify_principal name options...
+
+proc modify_principal { name args } {
+ global KADMIN_LOCAL
+ global REALMNAME
+
+ envstack_push
+ setup_kerberos_env kdc
+ spawn $KADMIN_LOCAL -r $REALMNAME
+ envstack_pop
+ expect_after {
+ eof {
+ fail "modprinc (kadmin.local)"
+ return 0
+ }
+ timeout {
+ fail "modprinc (kadmin.local)"
+ return 0
+ }
+ }
+ expect "kadmin.local: "
+ send "modprinc $args $name\r"
+ expect -re "modprinc \[^\n\r\]* $name"
+ expect -re "Principal .* modified."
+ send "quit\r"
+ expect eof
+ catch expect_after
+ if ![check_exit_status "kadmin.local modprinc"] {
+ perror "kadmin.local modprinc exited abnormally"
+ }
+ return 1
+}
+
+# kdc listens on +0..+3, depending whether we're testing reachable or not
+# client tries +1 and +6
+# kadmind +4
+# kpasswd +5
+# (nothing) +6
+# application servers (krlogind, telnetd, krshd, ftpd, etc) +8
+# iprop +9 (if enabled)
+# kpropd +10
+if [info exists PORTBASE] {
+ set portbase $PORTBASE
+} else {
+ set portbase 3085
+}
+
+set ulog 0
+
+# setup_kerberos_files
+# This procedure will create some Kerberos files which must be created
+# manually before trying to run any Kerberos programs. Returns 1 on
+# success, 0 on failure.
+
+proc setup_kerberos_files { } {
+ global REALMNAME
+ global hostname
+ global domain
+ global tmppwd
+ global supported_enctypes
+ global kdc_supported_enctypes
+ global last_passname_conf
+ global multipass_name
+ global master_key_type
+ global mode
+ global portbase
+ global ulog
+
+ if ![get_hostname] {
+ return 0
+ }
+
+ setup_krb5_conf client
+ setup_krb5_conf server
+ setup_krb5_conf kdc
+ setup_krb5_conf slave
+
+ # Create a kdc.conf file.
+ if { ![file exists $tmppwd/kdc.conf] \
+ || $last_passname_conf != $multipass_name } {
+ if ![info exists master_key_type] {
+ set master_key_type des-cbc-md5
+ }
+ set conffile [open $tmppwd/kdc.conf w]
+ puts $conffile "\[kdcdefaults\]"
+ puts $conffile " kdc_ports = $portbase,[expr 1 + $portbase],[expr 2 + $portbase]"
+ puts $conffile " kdc_tcp_ports = $portbase,[expr 1 + $portbase],[expr 2 + $portbase]"
+ puts $conffile ""
+ puts $conffile "\[realms\]"
+ puts $conffile " $REALMNAME = \{"
+# puts $conffile " database_name = $tmppwd/db"
+ puts $conffile " admin_database_name = $tmppwd/adb"
+ puts $conffile " admin_database_lockfile = $tmppwd/adb.lock"
+ # Testing with a colon in the name exercises default handling
+ # for pathnames.
+ puts $conffile " key_stash_file = $tmppwd/stash:foo"
+ puts $conffile " acl_file = $tmppwd/acl"
+ puts $conffile " kadmind_port = [expr 4 + $portbase]"
+ puts $conffile " kpasswd_port = [expr 5 + $portbase]"
+ puts $conffile " max_life = 1:00:00"
+ puts $conffile " max_renewable_life = 3:00:00"
+ puts $conffile " master_key_type = $master_key_type"
+ puts $conffile " master_key_name = master/key"
+ puts $conffile " supported_enctypes = $supported_enctypes"
+ puts $conffile " kdc_supported_enctypes = $kdc_supported_enctypes"
+ if { $mode == "tcp" } {
+ puts $conffile " kdc_ports = [expr 3 + $portbase]"
+ puts $conffile " kdc_tcp_ports = [expr 1 + $portbase],[expr 3 + $portbase]"
+ } else {
+ puts $conffile " kdc_ports = [expr 1 + $portbase]"
+ puts $conffile " kdc_tcp_ports = [expr 3 + $portbase]"
+ }
+ puts $conffile " default_principal_expiration = 2037.12.31.23.59.59"
+ puts $conffile " default_principal_flags = -postdateable forwardable"
+ puts $conffile " dict_file = $tmppwd/dictfile"
+ if { $ulog != 0 } {
+ puts $conffile " iprop_enable = true"
+ puts $conffile " iprop_port = [expr 9 + $portbase]"
+ puts $conffile " iprop_logfile = $tmppwd/db.ulog"
+ } else {
+ puts $conffile "# no ulog"
+ }
+ puts $conffile " \}"
+ puts $conffile ""
+ close $conffile
+ }
+
+ # Create a config file for the slave KDC (kpropd only, no normal
+ # KDC processes).
+ if { ![file exists $tmppwd/slave.conf] \
+ || $last_passname_conf != $multipass_name } {
+ if ![info exists master_key_type] {
+ set master_key_type des-cbc-md5
+ }
+ set conffile [open $tmppwd/slave.conf w]
+ puts $conffile "\[kdcdefaults\]"
+ puts $conffile " kdc_ports = $portbase,[expr 1 + $portbase],[expr 2 + $portbase]"
+ puts $conffile " kdc_tcp_ports = $portbase,[expr 1 + $portbase],[expr 2 + $portbase]"
+ puts $conffile ""
+ puts $conffile "\[realms\]"
+ puts $conffile " $REALMNAME = \{"
+# puts $conffile " database_name = $tmppwd/slave-db"
+ puts $conffile " admin_database_name = $tmppwd/slave-adb"
+ puts $conffile " admin_database_lockfile = $tmppwd/slave-adb.lock"
+ # Testing with a colon in the name exercises default handling
+ # for pathnames.
+ puts $conffile " key_stash_file = $tmppwd/slave-stash"
+ puts $conffile " acl_file = $tmppwd/slave-acl"
+ puts $conffile " kadmind_port = [expr 4 + $portbase]"
+ puts $conffile " kpasswd_port = [expr 5 + $portbase]"
+ puts $conffile " max_life = 1:00:00"
+ puts $conffile " max_renewable_life = 3:00:00"
+ puts $conffile " master_key_type = $master_key_type"
+ puts $conffile " master_key_name = master/key"
+ puts $conffile " supported_enctypes = $supported_enctypes"
+ puts $conffile " kdc_supported_enctypes = $kdc_supported_enctypes"
+ if { $mode == "tcp" } {
+ puts $conffile " kdc_ports = [expr 3 + $portbase]"
+ puts $conffile " kdc_tcp_ports = [expr 1 + $portbase],[expr 3 + $portbase]"
+ } else {
+ puts $conffile " kdc_ports = [expr 1 + $portbase]"
+ puts $conffile " kdc_tcp_ports = [expr 3 + $portbase]"
+ }
+ puts $conffile " default_principal_expiration = 2037.12.31.23.59.59"
+ puts $conffile " default_principal_flags = -postdateable forwardable"
+ puts $conffile " dict_file = $tmppwd/dictfile"
+ if { $ulog != 0 } {
+ puts $conffile " iprop_enable = true"
+ puts $conffile " iprop_port = [expr 9 + $portbase]"
+ puts $conffile " iprop_logfile = $tmppwd/slave-db.ulog"
+ } else {
+ puts $conffile "# no ulog"
+ }
+ puts $conffile " \}"
+ puts $conffile ""
+ close $conffile
+ }
+
+ # Create ACL file.
+ if ![file exists $tmppwd/acl] {
+ set aclfile [open $tmppwd/acl w]
+ puts $aclfile "krbtest/admin@$REALMNAME *"
+ puts $aclfile "kiprop/$hostname@$REALMNAME p"
+ close $aclfile
+ }
+
+ # Create dictfile file.
+ if ![file exists $tmppwd/dictfile] {
+ set dictfile [open $tmppwd/dictfile w]
+ puts $dictfile "weak_password"
+ close $dictfile
+ }
+
+ set last_passname_conf $multipass_name
+ return 1
+}
+
+proc reset_kerberos_files { } {
+ global tmppwd
+ file delete $tmppwd/kdc.conf $tmppwd/slave.conf $tmppwd/krb5.client.conf \
+ $tmppwd/krb5.server.conf $tmppwd/krb5.kdc.conf
+ setup_kerberos_files
+}
+
+proc setup_krb5_conf { {type client} } {
+ global tmppwd
+ global hostname
+ global domain
+ global REALMNAME
+ global last_passname_conf
+ global multipass_name
+ global default_tgs_enctypes
+ global default_tkt_enctypes
+ global permitted_enctypes
+ global mode
+ global portbase
+
+ # Create a krb5.conf file.
+ if { ![file exists $tmppwd/krb5.$type.conf] \
+ || $last_passname_conf != $multipass_name } {
+ set conffile [open $tmppwd/krb5.$type.conf w]
+ puts $conffile "\[libdefaults\]"
+ puts $conffile " default_realm = $REALMNAME"
+ puts $conffile " dns_lookup_kdc = false"
+ puts $conffile " allow_weak_crypto = true"
+ if [info exists default_tgs_enctypes($type)] {
+ puts $conffile \
+ " default_tgs_enctypes = $default_tgs_enctypes($type)"
+ }
+ if [info exists default_tkt_enctypes($type)] {
+ puts $conffile \
+ " default_tkt_enctypes = $default_tkt_enctypes($type)"
+ }
+ if [info exists permitted_enctypes($type)] {
+ puts $conffile \
+ " permitted_enctypes = $permitted_enctypes($type)"
+ }
+ if { $mode == "tcp" } {
+ puts $conffile " udp_preference_limit = 1"
+ }
+ puts $conffile ""
+ puts $conffile "\[realms\]"
+ puts $conffile " $REALMNAME = \{"
+ # There's probably nothing listening here. It would be a good
+ # test for the handling of a non-responsive KDC address. However,
+ # on some systems, like Tru64, we often wind up with the client's
+ # socket bound to this address, causing our request to appear in
+ # our incoming queue as if it were a response, which causes test
+ # failures. If we were running the client and KDC on different
+ # hosts, this would be okay....
+ #puts $conffile " kdc = $hostname:[expr 6 + $portbase]"
+ puts $conffile " kdc = $hostname:[expr 1 + $portbase]"
+ puts $conffile " admin_server = $hostname:[expr 4 + $portbase]"
+ puts $conffile " kpasswd_server = $hostname:[expr 5 + $portbase]"
+ puts $conffile " default_domain = $domain"
+ puts $conffile " database_module = foo_db2"
+ puts $conffile " \}"
+ puts $conffile ""
+ puts $conffile "\[domain_realm\]"
+ puts $conffile " .$domain = $REALMNAME"
+ puts $conffile " $domain = $REALMNAME"
+ puts $conffile ""
+ puts $conffile "\[logging\]"
+ puts $conffile " admin_server = FILE:$tmppwd/kadmind5.log"
+ puts $conffile " kdc = FILE:$tmppwd/kdc.log"
+ puts $conffile " default = FILE:$tmppwd/others.log"
+ puts $conffile ""
+ puts $conffile "\[dbmodules\]"
+ puts $conffile " foo_db2 = {"
+ puts $conffile " db_library = db2"
+ puts $conffile " database_name = $tmppwd/$type-db"
+ puts $conffile " }"
+ close $conffile
+ }
+}
+
+# Save the original values of the environment variables we are going
+# to muck with.
+
+# XXX deal with envstack later.
+
+if [info exists env(KRB5_CONFIG)] {
+ set orig_krb5_conf $env(KRB5_CONFIG)
+} else {
+ catch "unset orig_krb5_config"
+}
+
+if [info exists env(KRB5CCNAME)] {
+ set orig_krb5ccname $env(KRB5CCNAME)
+} else {
+ catch "unset orig_krb5ccname"
+}
+
+if [ info exists env(KRB5RCACHEDIR)] {
+ set orig_krb5rcachedir $env(KRB5RCACHEDIR)
+} else {
+ catch "unset orig_krb5rcachedir"
+}
+
+if [ info exists env(KERBEROS_SERVER)] {
+ set orig_kerberos_server $env(KERBEROS_SERVER)
+} else {
+ catch "unset orig_kerberos_server"
+}
+
+# setup_kerberos_env
+# Set the environment variables needed to run Kerberos programs.
+
+proc setup_kerberos_env { {type client} } {
+ global REALMNAME
+ global env
+ global tmppwd
+ global hostname
+ global portbase
+
+ # Set the environment variable KRB5_CONFIG to point to our krb5.conf file.
+ # All the Kerberos tools check KRB5_CONFIG.
+ # Actually, V5 doesn't currently use this.
+ set env(KRB5_CONFIG) $tmppwd/krb5.$type.conf
+ verbose "KRB5_CONFIG=$env(KRB5_CONFIG)"
+
+ # Direct the Kerberos programs at a local ticket file.
+ set env(KRB5CCNAME) $tmppwd/tkt
+ verbose "KRB5CCNAME=$env(KRB5CCNAME)"
+
+ # Direct the Kerberos server at a cache file stored in the
+ # temporary directory.
+ set env(KRB5RCACHEDIR) $tmppwd
+ verbose "KRB5RCACHEDIR=$env(KRB5RCACHEDIR)"
+
+ # Tell the Kerberos tools how to contact the $REALMNAME server.
+ set env(KERBEROS_SERVER) "$REALMNAME:$hostname:[expr 1 + $portbase]"
+ verbose "KERBEROS_SERVER=$env(KERBEROS_SERVER)"
+
+ # Set our kdc config file, if needed.
+ switch $type {
+ client -
+ server { catch {unset env(KRB5_KDC_PROFILE)} }
+ kdc { set env(KRB5_KDC_PROFILE) $tmppwd/kdc.conf }
+ slave { set env(KRB5_KDC_PROFILE) $tmppwd/slave.conf }
+ default { error "unknown config file type $type" }
+ }
+ if [info exists env(KRB5_KDC_PROFILE)] {
+ verbose "KRB5_KDC_PROFILE=$env(KRB5_KDC_PROFILE)"
+ }
+
+ # Create an environment setup script. (For convenience)
+ if ![file exists $tmppwd/$type-env.sh] {
+ set envfile [open $tmppwd/$type-env.sh w]
+ puts $envfile "KRB5_CONFIG=$env(KRB5_CONFIG)"
+ puts $envfile "KRB5CCNAME=$env(KRB5CCNAME)"
+ puts $envfile "KRB5RCACHEDIR=$env(KRB5RCACHEDIR)"
+ puts $envfile "KERBEROS_SERVER=$env(KERBEROS_SERVER)"
+ if [info exists env(KRB5_KDC_PROFILE)] {
+ puts $envfile "KRB5_KDC_PROFILE=$env(KRB5_KDC_PROFILE)"
+ } else {
+ puts $envfile "unset KRB5_KDC_PROFILE"
+ }
+ puts $envfile "export KRB5_CONFIG KRB5CCNAME KRB5RCACHEDIR"
+ puts $envfile "export KERBEROS_SERVER KRB5_KDC_PROFILE"
+ close $envfile
+ }
+ if ![file exists $tmppwd/$type-env.csh] {
+ set envfile [open $tmppwd/$type-env.csh w]
+ puts $envfile "setenv KRB5_CONFIG $env(KRB5_CONFIG)"
+ puts $envfile "setenv KRB5CCNAME $env(KRB5CCNAME)"
+ puts $envfile "setenv KRB5RCACHEDIR $env(KRB5RCACHEDIR)"
+ puts $envfile "setenv KERBEROS_SERVER $env(KERBEROS_SERVER)"
+ if [info exists env(KRB5_KDC_PROFILE)] {
+ puts $envfile "setenv KRB5_KDC_PROFILE $env(KRB5_KDC_PROFILE)"
+ } else {
+ puts $envfile "unsetenv KRB5_KDC_PROFILE"
+ }
+ close $envfile
+ }
+ return 1
+}
+
+# Restore the Kerberos environment, in case setup_kerberos_env was
+# already called by an earlier test.
+
+proc restore_kerberos_env { } {
+ global env
+ global orig_krb5_config
+ global orig_krb5ccname
+ global orig_krb5rcachedir
+ global orig_kerberos_server
+
+ if [info exists orig_krb5_config] {
+ set env(KRB5_CONFIG) $orig_krb5_config
+ } else {
+ catch "unset env(KRB5_CONFIG)"
+ }
+
+ if [info exists orig_krb5ccname] {
+ set env(KRB5CCNAME) $orig_krb5ccname
+ } else {
+ catch "unset env(KRB5CCNAME)"
+ }
+
+ if [info exists orig_krb5rcachedir] {
+ set env(KRB5RCACHEDIR) $orig_krb5rcachedir
+ } else {
+ catch "unset env(KRB5RCACHEDIR)"
+ }
+
+ if [info exists orig_kerberos_server] {
+ set env(KERBEROS_SERVER) $orig_kerberos_server
+ } else {
+ catch "unset env(KERBEROS_SERVER)"
+ }
+
+}
+
+# setup_kerberos_db
+# Initialize the Kerberos database. If the argument is non-zero, call
+# pass at relevant points. Returns 1 on success, 0 on failure.
+
+proc setup_kerberos_db { standalone } {
+ global REALMNAME KDB5_UTIL KADMIN_LOCAL KEY
+ global tmppwd hostname
+ global spawn_id
+ global des3_krbtgt tgt_support_desmd5
+ global multipass_name last_passname_db
+
+ set failall 0
+
+ if {!$standalone && [file exists $tmppwd/kdc-db.ok] \
+ && $last_passname_db == $multipass_name} {
+ return 1
+ }
+
+ delete_db
+
+ envstack_push
+ if { ![setup_kerberos_files] || ![setup_kerberos_env kdc] } {
+ set failall 1
+ }
+
+ # Set up a common expect_after for use in multiple places.
+ set def_exp_after {
+ timeout {
+ set test "$test (timeout)"
+ break
+ }
+ eof {
+ set test "$test (eof)"
+ break
+ }
+ }
+
+ set test "kdb5_util create"
+ set body {
+ if $failall {
+ break
+ }
+ #exec xterm
+ verbose "starting $test"
+ spawn $KDB5_UTIL -r $REALMNAME create -W
+ expect_after $def_exp_after
+
+ expect "Enter KDC database master key:"
+
+ set test "kdb5_util create (verify)"
+ send "masterkey$KEY\r"
+ expect "Re-enter KDC database master key to verify:"
+
+ set test "kdb5_util create"
+ send "masterkey$KEY\r"
+ expect {
+ -re "\[Cc\]ouldn't" {
+ expect eof
+ break
+ }
+ "Cannot find/read stored" exp_continue
+ "Warning: proceeding without master key" exp_continue
+ eof { }
+ }
+ catch expect_after
+ if ![check_exit_status kdb5_util] {
+ break
+ }
+ }
+ set ret [catch $body]
+ catch expect_after
+ if $ret {
+ set failall 1
+ if $standalone {
+ fail $test
+ }
+ } else {
+ if $standalone {
+ pass $test
+ }
+ }
+
+ # Stash the master key in a file.
+ set test "kdb5_util stash"
+ set body {
+ if $failall {
+ break
+ }
+ spawn $KDB5_UTIL -r $REALMNAME stash
+ verbose "starting $test"
+ expect_after $def_exp_after
+ expect "Enter KDC database master key:"
+ send "masterkey$KEY\r"
+ expect eof
+ catch expect_after
+ if ![check_exit_status kdb5_util] {
+ break
+ }
+ }
+ set ret [catch $body]
+ catch "expect eof"
+ catch expect_after
+ if $ret {
+ set failall 1
+ if $standalone {
+ fail $test
+ } else {
+ delete_db
+ }
+ } else {
+ if $standalone {
+ pass $test
+ }
+ }
+
+ # Add an admin user.
+ set test "kadmin.local ank krbtest/admin"
+ set body {
+ if $failall {
+ break
+ }
+ spawn $KADMIN_LOCAL -r $REALMNAME
+ verbose "starting $test"
+ expect_after $def_exp_after
+
+ expect "kadmin.local: "
+ send "ank krbtest/admin@$REALMNAME\r"
+ # It echos...
+ expect "ank krbtest/admin@$REALMNAME\r"
+ expect "Enter password for principal \"krbtest/admin@$REALMNAME\":"
+ send "adminpass$KEY\r"
+ expect "Re-enter password for principal \"krbtest/admin@$REALMNAME\":"
+ send "adminpass$KEY\r"
+ expect {
+ "Principal \"krbtest/admin@$REALMNAME\" created" { }
+ "Principal or policy already exists while creating*" { }
+ }
+ expect "kadmin.local: "
+ send "quit\r"
+ expect eof
+ catch expect_after
+ if ![check_exit_status kadmin_local] {
+ break
+ }
+ }
+ set ret [catch $body]
+ catch "expect eof"
+ catch expect_after
+ if $ret {
+ set failall 1
+ if $standalone {
+ fail $test
+ } else {
+ delete_db
+ }
+ } else {
+ if $standalone {
+ pass $test
+ }
+ }
+
+ # Add an incremental-propagation service.
+ set test "kadmin.local ank kiprop/$hostname"
+ set body {
+ if $failall {
+ break
+ }
+ spawn $KADMIN_LOCAL -r $REALMNAME
+ verbose "starting $test"
+ expect_after $def_exp_after
+
+ expect "kadmin.local: "
+ send "ank kiprop/$hostname@$REALMNAME\r"
+ # It echos...
+ expect "ank kiprop/$hostname@$REALMNAME\r"
+ expect "Enter password for principal \"kiprop/$hostname@$REALMNAME\":"
+ send "kiproppass$KEY\r"
+ expect "Re-enter password for principal \"kiprop/$hostname@$REALMNAME\":"
+ send "kiproppass$KEY\r"
+ expect {
+ "Principal \"kiprop/$hostname@$REALMNAME\" created" { }
+ "Principal or policy already exists while creating*" { }
+ }
+ expect "kadmin.local: "
+ send "quit\r"
+ expect eof
+ catch expect_after
+ if ![check_exit_status kadmin_local] {
+ break
+ }
+ }
+ set ret [catch $body]
+ catch "expect eof"
+ catch expect_after
+ if $ret {
+ set failall 1
+ if $standalone {
+ fail $test
+ } else {
+ delete_db
+ }
+ } else {
+ if $standalone {
+ pass $test
+ }
+ }
+
+ if $des3_krbtgt {
+ # Set the TGT key to DES3.
+ set test "kadmin.local TGT to DES3"
+ set body {
+ if $failall {
+ break
+ }
+ spawn $KADMIN_LOCAL -r $REALMNAME -e des3-cbc-sha1:normal
+ verbose "starting $test"
+ expect_after $def_exp_after
+
+ expect "kadmin.local: "
+ send "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r"
+ # It echos...
+ expect "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r"
+ expect {
+ "Key for \"krbtgt/$REALMNAME@$REALMNAME\" randomized." { }
+ }
+ expect "kadmin.local: "
+ send "quit\r"
+ expect eof
+ catch expect_after
+ if ![check_exit_status kadmin_local] {
+ break
+ }
+ }
+ set ret [catch $body]
+ catch "expect eof"
+ catch expect_after
+ if $ret {
+ set failall 1
+ if $standalone {
+ fail $test
+ } else {
+ delete_db
+ }
+ } else {
+ if $standalone {
+ pass $test
+ }
+ }
+ }
+ if $tgt_support_desmd5 {
+ # Make TGT support des-cbc-md5
+ set test "kadmin.local TGT to SUPPORT_DESMD5"
+ set body {
+ if $failall {
+ break
+ }
+ spawn $KADMIN_LOCAL -r $REALMNAME
+ verbose "starting $test"
+ expect_after $def_exp_after
+
+ expect "kadmin.local: "
+ send "modprinc +support_desmd5 krbtgt/$REALMNAME@$REALMNAME\r"
+ # It echos...
+ expect "modprinc +support_desmd5 krbtgt/$REALMNAME@$REALMNAME\r"
+ expect {
+ "Principal \"krbtgt/$REALMNAME@$REALMNAME\" modified.\r\n" { }
+ }
+ expect "kadmin.local: "
+ send "quit\r"
+ expect eof
+ catch expect_after
+ if ![check_exit_status kadmin_local] {
+ break
+ }
+ }
+ set ret [catch $body]
+ catch "expect eof"
+ catch expect_after
+ if $ret {
+ set failall 1
+ if $standalone {
+ fail $test
+ } else {
+ delete_db
+ }
+ } else {
+ if $standalone {
+ pass $test
+ }
+ }
+ }
+ envstack_pop
+
+ # create the admin database lock file
+ catch "exec touch $tmppwd/adb.lock"
+
+ set last_passname_db $multipass_name
+ return 1
+}
+
+proc start_tail { fname spawnid_var pid_var which standalone } {
+ upvar $spawnid_var spawnid
+ upvar $pid_var pid
+ global timeout
+
+ set f [open $fname a]
+
+ spawn tail -f $fname
+ set spawnid $spawn_id
+ set pid [exp_pid]
+
+ set markstr "===MARK $pid [clock format [clock seconds]] ==="
+ puts $f $markstr
+ flush $f
+
+ set p 0
+ set otimeout $timeout
+ set timeout 3
+ set ok 0
+ while { $ok == 0 && $p < 3 } {
+ expect {
+ -i $spawn_id
+ -ex "$markstr" { set ok 1 }
+ -re "\[^\r\n\]*\r\n" { exp_continue }
+ timeout {
+ # Some versions of GNU tail had a race condition where
+ # the first batch of data would be read from the end
+ # of the file, and then there was a brief window
+ # before calling stat and recording the size of the
+ # file. If the marker is written during that window,
+ # then yet another file modification is needed to get
+ # the first one noticed.
+ if { $p < 3 } {
+ verbose -log "no tail output yet, prodding with a blank line"
+ incr p
+ puts $f ""
+ flush $f
+ exp_continue
+ } else {
+ close $f
+ verbose -log "tail $fname output:"
+ verbose -log [exec tail $fname]
+ if {$standalone} {
+ verbose -log "tail -f timed out ($timeout sec) looking for mark in $which log"
+ fail "$which"
+ } else {
+ perror "$which tail -f timed out ($timeout sec) looking for mark in $which log"
+ }
+ stop_kerberos_daemons
+ exec kill $pid
+ expect -i $spawn_id eof
+ wait -i $spawn_id
+ set timeout $otimeout
+ return 0
+ }
+ }
+ }
+ }
+ close $f
+ set timeout $otimeout
+ return 1
+}
+
+# start_kerberos_daemons
+# A procedure to build a Kerberos database and start up the kerberos
+# and kadmind daemons. This sets the global variables kdc_pid,
+# kdc_spawn_id, kadmind_pid, and kadmind_spawn_id. The procedure
+# stop_kerberos_daemons should be used to stop the daemons. If the
+# argument is non-zero, call pass at relevant points. Returns 1 on
+# success, 0 on failure.
+
+proc start_kerberos_daemons { standalone } {
+ global BINSH
+ global REALMNAME
+ global KRB5KDC
+ global KADMIND
+ global KEY
+ global kdc_pid
+ global kdc_spawn_id
+ global kadmind_pid
+ global kadmind_spawn_id
+ global tmppwd
+ global env
+ global timeout
+
+ if ![setup_kerberos_db 0] {
+ return 0
+ }
+
+ if {$standalone} {
+ file delete $tmppwd/krb.log $tmppwd/kadmind.log $tmppwd/krb5kdc_rcache
+ }
+
+ # Start up the kerberos daemon
+ # Why are we doing all this with the log file you may ask.
+ # We need a handle on when the server starts. If we log the output
+ # of the server to say stderr, then if we stop looking for output,
+ # buffers will fill and the server will stop working....
+ # So, we look to see when a line is added to the log file and then
+ # check it..
+ # The same thing is done a little later for the kadmind
+ set kdc_lfile $tmppwd/kdc.log
+ set kadmind_lfile $tmppwd/kadmind5.log
+
+ if ![start_tail $kdc_lfile tailf_spawn_id tailf_pid krb5kdc $standalone] {
+ return 0
+ }
+
+ envstack_push
+ setup_kerberos_env kdc
+ spawn $KRB5KDC -r $REALMNAME -n full
+ envstack_pop
+ set kdc_pid [exp_pid]
+ set kdc_spawn_id $spawn_id
+
+ expect {
+ -i $tailf_spawn_id
+ -re "commencing operation\r\n" { }
+ -re "krb5kdc: \[a-zA-Z\]* - Cannot bind server socket to \[ 0-9a-fA-F:.\]*\r\n" {
+ verbose -log "warning: $expect_out(0,string)"
+ exp_continue
+ }
+ "no sockets set up?" {
+ if {$standalone} {
+ verbose -log "krb5kdc startup failed to bind listening sockets"
+ fail "krb5kdc"
+ } else {
+ perror "krb5kdc startup failed to bind listening sockets"
+ }
+ stop_kerberos_daemons
+ exec kill $tailf_pid
+ expect -i $tailf_spawn_id eof
+ wait -i $tailf_spawn_id
+ return 0
+ }
+ timeout {
+ if {$standalone} {
+ verbose -log "krb5kdc startup timed out"
+ fail "krb5kdc"
+ } else {
+ perror "krb5kdc startup timed out"
+ }
+ stop_kerberos_daemons
+ exec kill $tailf_pid
+ expect -i $tailf_spawn_id eof
+ wait -i $tailf_spawn_id
+ return 0
+ }
+ }
+ exec kill $tailf_pid
+ expect -i $tailf_spawn_id eof
+ wait -i $tailf_spawn_id
+
+ if {$standalone} {
+ pass "krb5kdc"
+ }
+
+ # Give the kerberos daemon a few seconds to get set up.
+# sleep 2
+
+ #
+ # Save setting of KRB5_KTNAME. We do not want to override kdc.conf
+ # file during kadmind startup. (this is in case user has KRB5_KTNAME
+ # set before starting make check)
+ #
+ if [info exists env(KRB5_KTNAME)] {
+ set start_save_ktname $env(KRB5_KTNAME)
+ }
+ catch "unset env(KRB5_KTNAME)"
+
+ if ![start_tail $kadmind_lfile tailf_spawn_id tailf_pid kadmind $standalone] {
+ return 0
+ }
+
+ # Start up the kadmind daemon
+ # XXXX kadmind uses stderr a lot. the sh -c and redirect can be
+ # removed when this is fixed
+ envstack_push
+ setup_kerberos_env kdc
+ spawn $BINSH -c "exec $KADMIND -r $REALMNAME -W -nofork 2>>$kadmind_lfile"
+ envstack_pop
+ set kadmind_pid [exp_pid]
+ set kadmind_spawn_id $spawn_id
+
+ # Restore KRB5_KTNAME
+ if [info exists start_save_ktname] {
+ set env(KRB5_KTNAME) $start_save_ktname
+ unset start_save_ktname
+ }
+
+ expect {
+ -i $tailf_spawn_id
+ "Seeding random number" exp_continue
+ "cannot initialize network" {
+ if {$standalone} {
+ verbose -log "kadmind failed network init"
+ fail "kadmind"
+ } else {
+ perror "kadmind failed network init"
+ }
+ stop_kerberos_daemons
+ exec kill $tailf_pid
+ expect -i $tailf_spawn_id eof
+ wait -i $tailf_spawn_id
+ return 0
+ }
+ "cannot bind to network address" {
+ if {$standalone} {
+ verbose -log "kadmind failed to bind socket"
+ fail "kadmind"
+ } else {
+ perror "kadmind failed to bind socket"
+ }
+ stop_kerberos_daemons
+ exec kill $tailf_pid
+ expect -i $tailf_spawn_id eof
+ wait -i $tailf_spawn_id
+ return 0
+ }
+ "No principal in keytab matches desired name" {
+ dump_db
+ exp_continue
+ }
+ "starting" { }
+ timeout {
+ if {$standalone} {
+ verbose -log "kadmind failed to start"
+ fail "kadmind"
+ } else {
+ verbose -log "kadmind failed to start"
+ perror "kadmind failed to start"
+ }
+#sleep 10
+ stop_kerberos_daemons
+ exec kill $tailf_pid
+ expect -i $tailf_spawn_id eof
+ wait -i $tailf_spawn_id
+ return 0
+ }
+ }
+ exec kill $tailf_pid
+ expect -i $tailf_spawn_id eof
+ wait -i $tailf_spawn_id
+
+ if {$standalone} {
+ pass "kadmind"
+ }
+
+ # Give the kadmind daemon a few seconds to get set up.
+# sleep 2
+
+ return 1
+}
+
+# stop_kerberos_daemons
+# Stop the kerberos daemons. Returns 1 on success, 0 on failure.
+
+proc stop_kerberos_daemons { } {
+ global kdc_pid
+ global kdc_spawn_id
+ global kadmind_pid
+ global kadmind_spawn_id
+
+ verbose "entered stop_kerberos_daemons"
+
+ if [info exists kdc_pid] {
+ if [catch "exec kill $kdc_pid" msg] {
+ verbose "kill kdc: $msg"
+ }
+ if [catch "expect -i $kdc_spawn_id eof" msg] {
+ verbose "expect kdc eof: $msg"
+ }
+ set kdc_list [wait -i $kdc_spawn_id]
+ verbose "wait -i $kdc_spawn_id returned $kdc_list (kdc)"
+ unset kdc_pid
+ unset kdc_list
+ }
+
+ if [info exists kadmind_pid] {
+ if [catch "exec kill $kadmind_pid" msg] {
+ verbose "kill kadmind: $msg"
+ }
+ if [catch "expect -i $kadmind_spawn_id eof" msg] {
+ verbose "expect kadmind eof: $msg"
+ }
+ set kadmind_list [wait -i $kadmind_spawn_id]
+ verbose "wait -i $kadmind_spawn_id returned $kadmind_list (kadmind5)"
+ unset kadmind_pid
+ unset kadmind_list
+ }
+
+ verbose "exiting stop_kerberos_daemons"
+
+ return 1
+}
+
+# add_kerberos_key
+# Add an key to the Kerberos database. start_kerberos_daemons must be
+# called before this procedure. If the standalone argument is
+# non-zero, call pass at relevant points. Returns 1 on success, 0 on
+# failure.
+
+proc add_kerberos_key { kkey standalone } {
+ global REALMNAME
+ global KADMIN
+ global KEY
+ global spawn_id
+
+ # Use kadmin to add an key.
+ set test "kadmin ank $kkey"
+ set body {
+ envstack_push
+ setup_kerberos_env client
+ spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank $kkey@$REALMNAME"
+ envstack_pop
+ verbose "starting $test"
+ expect_after {
+ "Cannot contact any KDC" {
+ set test "$test (lost KDC)"
+ break
+ }
+ timeout {
+ set test "$test (timeout)"
+ break
+ }
+ eof {
+ set test "$test (eof)"
+ break
+ }
+ }
+ expect -re "assword\[^\r\n\]*: *"
+ send "adminpass$KEY\r"
+ expect "Enter password for principal \"$kkey@$REALMNAME\":"
+ send "$kkey"
+ send "$KEY\r"
+ expect "Re-enter password for principal \"$kkey@$REALMNAME\":"
+ send "$kkey"
+ send "$KEY\r"
+ expect {
+ "Principal \"$kkey@$REALMNAME\" created" { }
+ "Principal or policy already exists while creating*" { }
+ }
+ expect eof
+ if ![check_exit_status kadmin] {
+ break
+ }
+ }
+ set ret [catch $body]
+ catch "expect eof"
+ catch expect_after
+ if $ret {
+ if $standalone {
+ fail $test
+ }
+ return 0
+ } else {
+ if $standalone {
+ pass $test
+ }
+ return 1
+ }
+}
+
+# dump_db
+proc dump_db { } {
+ global KADMIN_LOCAL
+ global REALMNAME
+
+ spawn $KADMIN_LOCAL -r $REALMNAME
+ expect_after {
+ eof {
+ perror "failed to get debugging dump of database (eof)"
+ }
+ timeout {
+ perror "failed to get debugging dump of database (timeout)"
+ }
+ }
+ expect "kadmin.local: "
+ send "getprincs\r"
+ expect "kadmin.local: "
+ send "quit\r"
+ expect eof
+ catch expect_after
+}
+
+# add_random_key
+# Add a key with a random password to the Kerberos database.
+# start_kerberos_daemons must be called before this procedure. If the
+# standalone argument is non-zero, call pass at relevant points.
+# Returns 1 on success, 0 on failure.
+
+proc add_random_key { kkey standalone } {
+ global REALMNAME
+ global KADMIN
+ global KEY
+ global spawn_id
+
+ # Use kadmin to add an key.
+ set test "kadmin ark $kkey"
+ set body {
+ envstack_push
+ setup_kerberos_env client
+ spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank -randkey $kkey@$REALMNAME"
+ envstack_pop
+ expect_after {
+ timeout {
+ set test "$test (timeout)"
+ break
+ }
+ eof {
+ set test "$test (eof)"
+ break
+ }
+ }
+ expect -re "assword\[^\r\n\]*: *"
+ send "adminpass$KEY\r"
+ expect {
+ "Principal \"$kkey@$REALMNAME\" created" { }
+ "Principal or policy already exists while creating*" { }
+ }
+ expect eof
+ if ![check_exit_status kadmin] {
+ break
+ }
+ }
+ if [catch $body] {
+ catch expect_after
+ if $standalone {
+ fail $test
+ }
+ return 0
+ } else {
+ catch expect_after
+ if $standalone {
+ pass $test
+ }
+ return 1
+ }
+}
+
+# setup_srvtab
+# Set up a srvtab file. start_kerberos_daemons and add_random_key
+# $id/$hostname must be called before this procedure. If the
+# argument is non-zero, call pass at relevant points. Returns 1 on
+# success, 0 on failure. If the id field is not provided, host is used.
+
+proc setup_srvtab { standalone {id host} } {
+ global REALMNAME
+ global KADMIN_LOCAL
+ global KEY
+ global tmppwd
+ global hostname
+ global spawn_id
+ global last_service
+
+ if {!$standalone && [file exists $tmppwd/srvtab] && $last_service == $id} {
+ return 1
+ }
+
+ file delete $tmppwd/srvtab $tmppwd/srvtab.old
+
+ if ![get_hostname] {
+ return 0
+ }
+
+ file delete $hostname-new-srvtab
+
+ envstack_push
+ setup_kerberos_env kdc
+ spawn $KADMIN_LOCAL -r $REALMNAME
+ envstack_pop
+ expect_after {
+ -re "(.*)\r\nkadmin.local: " {
+ fail "kadmin.local srvtab (unmatched output: $expect_out(1,string))"
+ if {!$standalone} {
+ file delete $tmppwd/srvtab
+ }
+ catch "expect_after"
+ return 0
+ }
+ timeout {
+ fail "kadmin.local srvtab"
+ if {!$standalone} {
+ file delete $tmppwd/srvtab
+ }
+ catch "expect_after"
+ return 0
+ }
+ eof {
+ fail "kadmin.local srvtab"
+ if {!$standalone} {
+ file delete $tmppwd/srvtab
+ }
+ catch "expect_after"
+ return 0
+ }
+ }
+ expect "kadmin.local: "
+ send "xst -k $hostname-new-srvtab $id/$hostname kiprop/$hostname\r"
+ expect "xst -k $hostname-new-srvtab $id/$hostname kiprop/$hostname\r\n"
+ expect {
+ -re ".*Entry for principal $id/$hostname.* added to keytab WRFILE:$hostname-new-srvtab." { }
+ -re "\r\nkadmin.local: " {
+ if {$standalone} {
+ fail "kadmin.local srvtab"
+ } else {
+ file delete $tmppwd/srvtab
+ }
+ catch expect_after
+ return 0
+ }
+ }
+ expect "kadmin.local: "
+ send "quit\r"
+ expect eof
+ catch expect_after
+ if ![check_exit_status "kadmin.local srvtab"] {
+ if {!$standalone} {
+ file delete $tmppwd/srvtab
+ }
+ return 0
+ }
+
+ catch "exec mv -f $hostname-new-srvtab $tmppwd/srvtab" exec_output
+ if ![string match "" $exec_output] {
+ verbose -log "$exec_output"
+ perror "can't mv new srvtab"
+ return 0
+ }
+
+ if {$standalone} {
+ pass "kadmin.local srvtab"
+ }
+
+ # Make the srvtab file globally readable in case we are using a
+ # root shell and the srvtab is NFS mounted.
+ catch "exec chmod a+r $tmppwd/srvtab"
+
+ # Remember what we just extracted
+ set last_service $id
+
+ return 1
+}
+
+# kinit
+# Use kinit to get a ticket. If the argument is non-zero, call pass
+# at relevant points. Returns 1 on success, 0 on failure.
+
+proc kinit { name pass standalone } {
+ 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"
+ return 0
+ }
+ eof {
+ fail "kinit"
+ return 0
+ }
+ }
+ send "$pass\r"
+ expect eof
+ if ![check_exit_status kinit] {
+ return 0
+ }
+
+ if {$standalone} {
+ pass "kinit"
+ }
+
+ return 1
+}
+
+proc kinit_kt { name keytab standalone testname } {
+ 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 -k -t $keytab $name@$REALMNAME
+ expect {
+ timeout {
+ fail "kinit $testname"
+ return 0
+ }
+ eof { }
+ }
+ if ![check_exit_status "kinit $testname"] {
+ return 0
+ }
+
+ if {$standalone} {
+ pass "kinit $testname"
+ }
+
+ return 1
+}
+
+# List tickets. Requires client and server names, and test name.
+# Checks that klist exist status is zero.
+# Records pass or fail, and returns 1 or 0.
+proc do_klist { myname servname testname } {
+ global KLIST
+ global tmppwd
+
+ spawn $KLIST -5 -e
+ expect {
+ -re "Ticket cache:\[ \]*(.+:)?$tmppwd/tkt.*Default principal:\[ \]*$myname.*$servname\r\n" {
+ verbose "klist started"
+ }
+ timeout {
+ fail $testname
+ return 0
+ }
+ eof {
+ fail $testname
+ return 0
+ }
+ }
+
+ expect eof
+
+ if ![check_exit_status $testname] {
+ return 0
+ }
+ pass $testname
+ return 1
+}
+
+proc do_klist_kt { keytab testname } {
+ global KLIST
+ global tmppwd
+
+ spawn $KLIST -5 -e -k $keytab
+ expect {
+ -re "Keytab name:\[ \]*(.+:)?.*KVNO Principal\r\n---- -*\r\n" {
+ verbose "klist started"
+ }
+ timeout {
+ fail $testname
+ return 0
+ }
+ eof {
+ fail $testname
+ return 0
+ }
+ }
+ set more 1
+ while {$more} {
+ expect {
+ -re { *[0-9][0-9]* *[a-zA-Z/@.-]* \([/a-zA-Z 0-9-]*\) *\r\n} {
+ verbose -log "key: $expect_out(buffer)"
+ }
+ eof { set more 0 }
+ }
+ }
+
+ if ![check_exit_status $testname] {
+ return 0
+ }
+ pass $testname
+ return 1
+}
+
+proc do_klist_err { testname } {
+ global KLIST
+ global spawn_id
+
+ spawn $KLIST -5
+ # Might say "credentials cache" or "credentials cache file".
+ expect {
+ -re "klist: No credentials cache.*found.*\r\n" {
+ verbose "klist started"
+ }
+ timeout {
+ fail $testname
+ return 0
+ }
+ eof {
+ fail $testname
+ return 0
+ }
+ }
+ # We can't use check_exit_status, because we expect an exit status
+ # of 1.
+ catch "expect eof"
+ set status_list [wait -i $spawn_id]
+ verbose "wait -i $spawn_id returned $status_list ($testname)"
+ if { [lindex $status_list 2] != 0 } {
+ fail "$testname (bad exit status) $status_list"
+ return 0
+ } else { if { [lindex $status_list 3] != 1 } {
+ fail "$testname (bad exit status) $status_list"
+ return 0
+ } else {
+ pass $testname
+ } }
+ return 1
+}
+
+proc do_kdestroy { testname } {
+ global KDESTROY
+ global spawn_id
+
+ spawn $KDESTROY -5
+ if ![check_exit_status $testname] {
+ fail $testname
+ return 0
+ }
+ pass $testname
+ return 1
+}
+
+proc xst { keytab name } {
+ global KADMIN_LOCAL
+ global REALMNAME
+
+ envstack_push
+ setup_kerberos_env kdc
+ spawn $KADMIN_LOCAL -r $REALMNAME
+ envstack_pop
+ catch expect_after
+ expect_after {
+ -re "(.*)\r\nkadmin.local: " {
+ fail "kadmin.local xst $keytab (unmatched output: $expect_out(1,string)"
+ catch "expect_after"
+ return 0
+ }
+ timeout {
+ fail "kadmin.local xst $keytab (timeout)"
+ catch "expect_after"
+ return 0
+ }
+ eof {
+ fail "kadmin.local xst $keytab (eof)"
+ catch "expect_after"
+ return 0
+ }
+ }
+ expect "kadmin.local: "
+ send "xst -k $keytab $name\r"
+ expect -re "xst -k \[^\r\n\]*\r\n.*Entry for principal .* added to keytab WRFILE:.*\r\nkadmin.local: "
+ send "quit\r"
+ expect eof
+ catch expect_after
+ if ![check_exit_status "kadmin.local $keytab"] {
+ perror "kadmin.local xst $keytab exited abnormally"
+ return 0
+ }
+ return 1
+}
+
+# v4_compatible_enctype
+# Returns 1 if v4 testing is enabled this passes encryption types are compatable with kerberos 4 work
+proc v4_compatible_enctype {} {
+ global supported_enctypes
+ global KRBIV
+
+ if ![info exists KRBIV] {
+ return 0;
+ }
+
+ if { $KRBIV && [string first des-cbc-crc:v4 "$supported_enctypes"] >= 0} {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+# Set up a root shell using rlogin $hostname -l root. This is used
+# when testing the daemons that must be run as root, such as telnetd
+# or rlogind. This sets the global variables rlogin_spawn_id and
+# rlogin_pid. Returns 1 on success, 0 on failure.
+#
+# This procedure will only succeed if the person running the test has
+# a valid ticket for a name listed in the /.klogin file. Naturally,
+# Kerberos must already be installed on this machine. It's a pain,
+# but I can't think of a better approach.
+
+if ![info exists can_get_root] { set can_get_root yes }
+
+proc setup_root_shell { testname } {
+ global BINSH
+ global ROOT_PROMPT
+ global KEY
+ global RLOGIN
+ global RLOGIN_FLAGS
+ global hostname
+ global rlogin_spawn_id
+ global rlogin_pid
+ global tmppwd
+ global env
+ global krb5_init_vars
+ global can_get_root
+
+ global timeout
+
+ if [string match $can_get_root no] {
+ note "$testname test requires ability to log in as root"
+ unsupported $testname
+ return 0
+ }
+
+ # Make sure we are using the original values of the environment
+ # variables. This means that the caller must call
+ # setup_kerberos_env after calling this procedure.
+
+ # XXX fixme to deal with envstack
+ restore_kerberos_env
+
+ set me [exec whoami]
+ if [string match root $me] {
+ return [setup_root_shell_noremote $testname]
+ }
+
+ if ![get_hostname] {
+ set can_get_root no
+ return 0
+ }
+
+ # If you have not installed Kerberos on your system, and you want
+ # to run these tests, you can do it if you are willing to put your
+ # root password in this file (this is not a very good idea, but
+ # it's safe enough if you disconnect from the network and remember
+ # to remove the password later). Change the rlogin in the next
+ # line to be /usr/ucb/rlogin (or whatever is appropriate for your
+ # system). Then change the lines after "word:" a few lines
+ # farther down to be
+ # send "rootpassword\r"
+ # exp_continue
+
+ eval spawn $RLOGIN $hostname -l root $RLOGIN_FLAGS
+ set rlogin_spawn_id $spawn_id
+ set rlogin_pid [exp_pid]
+ set old_timeout $timeout
+ set timeout 300
+ set got_refused 0
+
+ expect {
+ -re {connect to address [0-9a-fA-F.:]*: Connection refused} {
+ note $expect_out(buffer)
+ set got_refused 1
+ exp_continue
+ }
+ -re "word:|erberos rlogin failed|ection refused|ection reset by peer|not authorized|Ticket expired|authenticity of" {
+ note "$testname test requires ability to rlogin as root"
+ unsupported "$testname"
+ set timeout $old_timeout
+ stop_root_shell
+ set can_get_root no
+ return 0
+ }
+ "Cannot assign requested address" {
+ note "$testname: rlogin as root 'cannot assign requested address'"
+ unsupported "$testname"
+ set timeout $old_timeout
+ stop_root_shell
+ set can_get_root no
+ return 0
+ }
+ -re "usage: rlogin|illegal option -- x|invalid option -- x" {
+ note "$testname: rlogin doesn't like command-line flags"
+ unsupported "$testname"
+ set timeout $old_timeout
+ stop_root_shell
+ set can_get_root no
+ return 0
+ }
+ -re "$ROOT_PROMPT" { }
+ timeout {
+ perror "timeout from rlogin $hostname -l root"
+ perror "If you have an unusual root prompt,"
+ perror "try running with ROOT_PROMPT=\"regexp\""
+ set timeout $old_timeout
+ stop_root_shell
+ set can_get_root no
+ return 0
+ }
+ eof {
+ if {$got_refused} {
+ # reported some errors, continued, and failed
+ note "$testname test requires ability to log in as root"
+ unsupported $testname
+ } else {
+ # unknown problem?
+# perror "eof from rlogin $hostname -l root"
+ note "eof (and unrecognized messages?) from rlogin $hostname -l root"
+ note "$testname test requires ability to log in as root"
+ unsupported $testname
+ }
+ stop_root_shell
+ set timeout $old_timeout
+ catch "expect_after"
+ set can_get_root no
+ return 0
+ }
+ }
+
+ expect_after {
+ timeout {
+ perror "timeout from rlogin $hostname -l root"
+ stop_root_shell
+ set timeout $old_timeout
+ catch "expect_after"
+ set can_get_root no
+ return 0
+ }
+ eof {
+ perror "eof from rlogin $hostname -l root"
+ stop_root_shell
+ set timeout $old_timeout
+ catch "expect_after"
+ set can_get_root no
+ return 0
+ }
+ }
+
+ # Make sure the root shell is using /bin/sh.
+ send "$BINSH\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ }
+
+ # Set up a shell variable tmppwd. The callers use this to keep
+ # command line lengths down. The command line length is important
+ # because we are feeding input to a shell via a pty. On some
+ # systems a pty will only accept 255 characters.
+ send "tmppwd=$tmppwd\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ }
+
+ # Set up our krb5.conf
+ send "KRB5_CONFIG=$tmppwd/krb5.server.conf\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ }
+ send "export KRB5_CONFIG\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ }
+
+ # Move over to the right directory.
+ set dir [pwd]
+ send "cd $dir\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ "$dir:" {
+ perror "root shell can not cd to $dir"
+ set timeout $old_timeout
+ stop_root_shell
+ set can_get_root no
+ return 0
+ }
+ }
+
+ expect_after
+ set timeout $old_timeout
+
+ return 1
+}
+
+proc setup_root_shell_noremote { testname } {
+ global BINSH
+ global ROOT_PROMPT
+ global KEY
+ global hostname
+ global rlogin_spawn_id
+ global rlogin_pid
+ global tmppwd
+ global env
+
+ eval spawn $BINSH
+ set rlogin_spawn_id $spawn_id
+ set rlogin_pid [exp_pid]
+
+ expect_after {
+ timeout {
+ perror "timeout from root shell"
+ stop_root_shell
+ catch "expect_after"
+ return 0
+ }
+ eof {
+ perror "eof from root shell"
+ stop_root_shell
+ catch "expect_after"
+ return 0
+ }
+ }
+ expect {
+ -re "$ROOT_PROMPT" { }
+ }
+
+ # Set up a shell variable tmppwd. The callers use this to keep
+ # command line lengths down. The command line length is important
+ # because we are feeding input to a shell via a pty. On some
+ # systems a pty will only accept 255 characters.
+ send "tmppwd=$tmppwd\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ }
+
+ # Set up our krb5.conf
+ send "KRB5_CONFIG=$tmppwd/krb5.server.conf\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ }
+ send "export KRB5_CONFIG\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ }
+
+ # Move over to the right directory.
+ set dir [pwd]
+ send "cd $dir\r"
+ expect {
+ -re "$ROOT_PROMPT" { }
+ "$dir:" {
+ perror "root shell can not cd to $dir"
+ stop_root_shell
+ return 0
+ }
+ }
+
+ expect_after
+
+ return 1
+}
+
+# Kill off a root shell started by setup_root_shell.
+
+proc stop_root_shell { } {
+ global rlogin_spawn_id
+ global rlogin_pid
+
+ catch "close -i $rlogin_spawn_id"
+ catch "exec kill $rlogin_pid"
+ sleep 1
+ catch "exec kill -9 $rlogin_pid"
+ catch "wait -i $rlogin_spawn_id"
+}
+
+# Check the date. The string will be the output of date on this
+# system, and we must make sure that it is in the same timezone as the
+# output of date run a second time. The first date will be run on an
+# rlogin or some such connection to the local system. This is to test
+# to make sure that the TZ environment variable is handled correctly.
+# Returns 1 on sucess, 0 on failure.
+
+proc check_date { date } {
+ catch "exec date" ndate
+ set atz ""
+ set ntz ""
+ scan $date "%s %s %d %d:%d:%d %s %d" adow amon adom ahr amn asc atz ayr
+ scan $ndate "%s %s %d %d:%d:%d %s %d" ndow nmon ndom nhr nmn nsc ntz nyr
+ if { $atz != $ntz } {
+ verbose -log "date check failed: $atz != $ntz"
+ return 0
+ }
+ return 1
+}
+
+proc touch { file } {
+ set f [open $file "a"]
+ puts $f ""
+ close $f
+}
+
+# Implement this in tcl someday?
+proc tail1 { file } {
+ exec tail -1 $file
+}
+
+# setup_wrapper
+# Sets up a wraper script to set the runtime shared library environment
+# variables and then executes a specific command. This is used to allow
+# a "rsh klist" or telnetd to execute login.krb5.
+proc setup_wrapper { file command } {
+ global BINSH
+ global env
+
+ # We will start with a BINSH script
+ file delete $file
+
+ set f [open $file "w" 0777]
+ puts $f "#!$BINSH"
+ puts $f "KRB5_CONFIG=$env(KRB5_CONFIG)"
+ puts $f "export KRB5_CONFIG"
+ puts $f "exec $command"
+ close $f
+
+ return 1
+}
+
+proc krb_exit { } {
+ stop_kerberos_daemons
+}
+
+# helpful sometimes for debugging the test suite
+proc export_debug_envvars { } {
+ global env
+ foreach i {KDB5_UTIL KRB5KDC KADMIND KADMIN KADMIN_LOCAL KINIT KTUTIL KLIST RLOGIN RLOGIN_FLAGS RLOGIND FTP FTPD KPASSWD REALMNAME GSSCLIENT KPROPLOG} {
+ global $i
+ if [info exists $i] { set env($i) [set $i] }
+ }
+}
+proc spawn_xterm { } {
+ export_debug_envvars
+ exec "xterm"
+}
+proc spawn_shell { } {
+ export_debug_envvars
+ spawn "sh"
+ exp_interact
+}
Added: trunk/tests/deps
===================================================================
--- trunk/tests/deps 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/deps 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,5 @@
+#
+# Generated makefile dependencies follow.
+#
+$(OUTPRE)t_inetd.$(OBJEXT): $(BUILDTOP)/autoconf.h \
+ t_inetd.c
Added: trunk/tests/krb-root/rlogin.exp
===================================================================
--- trunk/tests/krb-root/rlogin.exp 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/krb-root/rlogin.exp 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,322 @@
+# Kerberos rlogin test.
+# This is a DejaGnu test script.
+# This script tests Kerberos rlogin.
+# Written by Ian Lance Taylor, Cygnus Support, <ian at cygnus.com>.
+
+# Find the programs we need. We use the binaries from the build tree
+# if they exist. If they do not, then they must be in PATH. We
+# expect $objdir to be .../kerberos/src.
+
+if ![info exists KRLOGIN] {
+ set KRLOGIN [findfile $objdir/../bsd/rlogin]
+}
+
+if ![info exists KRLOGIND] {
+ set KRLOGIND [findfile $objdir/../bsd/klogind]
+}
+
+if ![info exists LOGINKRB5] {
+ set LOGINKRB5 [findfile $objdir/../bsd/login.krb5]
+}
+
+# Start up a root shell.
+if ![setup_root_shell rlogin] {
+ return
+}
+
+# Make sure .k5login is reasonable.
+if ![check_k5login rlogin] {
+ stop_root_shell
+ return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+ || ![setup_kerberos_files] \
+ || ![setup_kerberos_env] \
+ || ![setup_kerberos_db 0]} {
+ stop_root_shell
+ return
+}
+
+# A procedure to start up the rlogin daemon.
+
+proc start_rlogin_daemon { option } {
+ global REALMNAME
+ global KRLOGIND
+ global LOGINKRB5
+ global ROOT_PROMPT
+ global tmppwd
+ global hostname
+ global rlogin_spawn_id
+ global krlogind_pid
+ global portbase
+
+ # The -p argument tells it to accept a single connection, so we
+ # don't need to use inetd. The 3543 is the port to listen at.
+ # Note that tmppwd here is a shell variable, which is set in
+ # setup_root_shell, not a TCL variable. The sh -c is to workaround
+ # the broken controlling tty handling in hpux, and shouldn't hurt
+ # anything else.
+ send -i $rlogin_spawn_id "sh -c \"$KRLOGIND -k -c -D [expr 8 + $portbase] -S \$tmppwd/srvtab -M $REALMNAME -L $LOGINKRB5 $option\" &\r"
+ expect {
+ -i $rlogin_spawn_id
+ -re "$ROOT_PROMPT" { }
+ timeout {
+ send_error "ERROR: timeout from rlogin $hostname -l root\n"
+ return
+ }
+ eof {
+ send_error "ERROR: eof from rlogin $hostname -l root\n"
+ return
+ }
+ }
+ send -i $rlogin_spawn_id "echo \$!\r"
+ expect {
+ -i $rlogin_spawn_id
+ -re "\[0-9\]+" {
+ set krlogind_pid $expect_out(0,string)
+ verbose "krlogind process ID is $krlogind_pid"
+ }
+ timeout {
+ send_error "ERROR: timeout from rlogin $hostname -l root\n"
+ return
+ }
+ eof {
+ send_error "ERROR: eof from rlogin $hostname -l root\n"
+ return
+ }
+ }
+ expect {
+ -i $rlogin_spawn_id
+ -re "$ROOT_PROMPT" { }
+ timeout {
+ send_error "ERROR: timeout from rlogin $hostname -l root\n"
+ return
+ }
+ eof {
+ send_error "ERROR: eof from rlogin $hostname -l root\n"
+ return
+ }
+ }
+
+ # Give the rlogin daemon a few seconds to get set up.
+ sleep 2
+}
+
+# A procedure to stop the rlogin daemon.
+
+proc stop_rlogin_daemon { } {
+ global krlogind_pid
+
+ if [info exists krlogind_pid] {
+ catch "exec kill $krlogind_pid"
+ unset krlogind_pid
+ }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc rlogin_test { } {
+ global REALMNAME
+ global KRLOGIN
+ global BINSH
+ global SHELL_PROMPT
+ global KEY
+ global hostname
+ global hostname
+ global env
+ global portbase
+
+ # Start up the kerberos and kadmind daemons and get a srvtab and a
+ # ticket file.
+ if {![start_kerberos_daemons 0] \
+ || ![add_kerberos_key host/$hostname 0] \
+ || ![setup_srvtab 0] \
+ || ![add_kerberos_key $env(USER) 0] \
+ || ![kinit $env(USER) $env(USER)$KEY 0]} {
+ return
+ }
+
+ # Start up the rlogin daemon.
+ start_rlogin_daemon -k
+
+ # Make an rlogin connection.
+ spawn $KRLOGIN $hostname -k $REALMNAME -D [expr 8 + $portbase]
+
+ expect_after {
+ timeout {
+ fail "$testname (timeout)"
+ catch "expect_after"
+ return
+ }
+ "onnection closed." {
+ fail "$testname (connection closed)"
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ catch "expect_after"
+ return
+ }
+ }
+
+ set testname "rlogin"
+ expect {
+ -re "$SHELL_PROMPT" {
+ pass $testname
+ }
+ }
+
+ # Switch to /bin/sh to try to avoid confusion from the shell
+ # prompt.
+ set testname "shell"
+ send "$BINSH\r"
+ expect "$BINSH"
+ expect -re "$SHELL_PROMPT"
+
+ set testname "date"
+ send "date\r"
+ expect "date"
+ expect {
+ -re "\[A-Za-z0-9 :\]+\[\r\n\]+" {
+ if [check_date $expect_out(0,string)] {
+ pass "date"
+ } else {
+ fail "date"
+ }
+ }
+ }
+ expect -re "$SHELL_PROMPT"
+
+ set testname "exit"
+ send "exit\r"
+ expect -re "$SHELL_PROMPT"
+ send "exit\r"
+ expect {
+ "onnection closed." {
+ pass $testname
+ }
+ }
+ # This last expect seems useless, but without it the rlogin process
+ # sometimes hangs on HP-UX, in a tcsetattr call with TCSADRAIN.
+ expect {
+ "\r" { }
+ }
+
+ expect_after
+
+ if [check_exit_status "exit status"] {
+ pass "exit status"
+ }
+
+ # The rlogin daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_rlogin_daemon
+
+ # Try an encrypted connection.
+ start_rlogin_daemon -e
+ spawn $KRLOGIN $hostname -x -k $REALMNAME -D [expr 8 + $portbase]
+
+ expect_after {
+ timeout {
+ fail "$testname (timeout)"
+ catch "expect_after"
+ return
+ }
+ "onnection closed" {
+ fail "$testname (connection closed)"
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ catch "expect_after"
+ return
+ }
+ }
+
+ set testname "encrypted rlogin"
+ expect -re "encrypting .* transmissions"
+ expect {
+ -re "$SHELL_PROMPT" {
+ pass $testname
+ }
+ }
+
+ # Switch to /bin/sh to try to avoid confusion from the shell
+ # prompt.
+ set testname "shell"
+ send "$BINSH\r"
+ expect "$BINSH"
+ expect -re "$SHELL_PROMPT"
+
+ # Make sure the encryption is not destroying the text.
+ set testname "echo"
+ send "echo hello\r"
+ expect "echo hello"
+ expect "hello"
+ expect {
+ -re "$SHELL_PROMPT" {
+ pass $testname
+ }
+ }
+
+ # Send some characters which might cause an interrupt, and then
+ # make sure we can still talk to the shell.
+ set testname "interrupt characters"
+ send "\003\177\034\r"
+ expect -re "$SHELL_PROMPT"
+ send "echo hello\r"
+ expect "echo hello"
+ expect "hello"
+ expect {
+ -re "$SHELL_PROMPT" {
+ pass $testname
+ }
+ }
+
+ set testname "~."
+ send "~."
+ expect {
+ "Closed connection.\r" {
+ pass $testname
+ }
+ "onnection closed" {
+ pass $testname
+ }
+ }
+
+ expect_after
+
+ if [check_exit_status "exit status"] {
+ pass "exit status"
+ }
+
+ # The rlogin daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_rlogin_daemon
+}
+
+# Run the test. Logging in sometimes takes a while, so increase the
+# timeout.
+set oldtimeout $timeout
+set timeout 60
+set status [catch rlogin_test msg]
+set timeout $oldtimeout
+
+# Shut down the kerberos daemons, the rlogin daemon, and the root
+# process.
+stop_kerberos_daemons
+
+stop_rlogin_daemon
+
+stop_root_shell
+
+if { $status != 0 } {
+ send_error "ERROR: error in rlogin.exp\n"
+ send_error "$msg\n"
+ exit 1
+}
Added: trunk/tests/krb-root/telnet.exp
===================================================================
--- trunk/tests/krb-root/telnet.exp 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/krb-root/telnet.exp 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,451 @@
+# Kerberos telnet test.
+# This is a DejaGnu test script.
+# This script tests Kerberos telnet.
+# Written by Ian Lance Taylor, Cygnus Support, <ian at cygnus.com>.
+
+# Find the programs we need. We use the binaries from the build tree
+# if they exist. If they do not, then they must be in PATH. We
+# expect $objdir to be .../kerberos/src.
+
+if ![info exists TELNET] {
+ set TELNET [findfile $objdir/../telnet/telnet/telnet]
+}
+
+if ![info exists TELNETD] {
+ set TELNETD [findfile $objdir/../telnet/telnetd/telnetd]
+}
+
+if ![info exists LOGINKRB5] {
+ set LOGINKRB5 [findfile $objdir/../bsd/login.krb5]
+}
+
+if ![regexp des- $supported_enctypes] {
+ # Telnet needs a DES enctype.
+ verbose "Skipping telnet tests for lack of DES support."
+ return
+}
+
+# A procedure to start up the telnet daemon.
+
+proc start_telnet_daemon { args } {
+ global REALMNAME
+ global TELNETD
+ global LOGINKRB5
+ global ROOT_PROMPT
+ global tmppwd
+ global hostname
+ global rlogin_spawn_id
+ global telnetd_pid
+ global portbase
+
+ # Setup the shared library wrapper for login.krb5
+ if ![file exists $tmppwd/login.wrap] {
+ setup_wrapper $tmppwd/login.wrap "$LOGINKRB5 $*"
+ }
+
+ # The -debug argument tells it to accept a single connection, so
+ # we don't need to use inetd. The portbase+8 is the port to listen at.
+ # Note that tmppwd here is a shell variable, which is set in
+ # setup_root_shell, not a TCL variable.
+ send -i $rlogin_spawn_id "sh -c \"$TELNETD $args -debug -t \$tmppwd/srvtab -R $REALMNAME -L $tmppwd/login.wrap [expr 8 + $portbase]\" &\r"
+ expect {
+ -i $rlogin_spawn_id
+ -re "$ROOT_PROMPT" { }
+ timeout {
+ send_error "ERROR: timeout from rlogin $hostname -l root\n"
+ return
+ }
+ eof {
+ send_error "ERROR: eof from rlogin $hostname -l root\n"
+ return
+ }
+ }
+ send -i $rlogin_spawn_id "echo \$!\r"
+ expect {
+ -i $rlogin_spawn_id
+ -re "\[0-9\]+" {
+ set telnetd_pid $expect_out(0,string)
+ verbose "telnetd process ID is $telnetd_pid"
+ }
+ timeout {
+ send_error "ERROR: timeout from rlogin $hostname -l root\n"
+ return
+ }
+ eof {
+ send_error "ERROR: eof from rlogin $hostname -l root\n"
+ return
+ }
+ }
+ expect {
+ -i $rlogin_spawn_id
+ -re "$ROOT_PROMPT" { }
+ timeout {
+ send_error "ERROR: timeout from rlogin $hostname -l root\n"
+ return
+ }
+ eof {
+ send_error "ERROR: eof from rlogin $hostname -l root\n"
+ return
+ }
+ }
+
+ # Give the telnet daemon a few seconds to get set up.
+ sleep 2
+}
+
+# A procedure to stop the telnet daemon.
+
+proc stop_telnet_daemon { } {
+ global telnetd_pid
+
+ if [info exists telnetd_pid] {
+ catch "exec kill $telnetd_pid"
+ unset telnetd_pid
+ }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc telnet_test { } {
+ global REALMNAME
+ global TELNET
+ global BINSH
+ global SHELL_PROMPT
+ global KEY
+ global hostname
+ global localhostname
+ global env
+ global portbase
+
+ # Start up the kerberos and kadmind daemons and get a srvtab and a
+ # ticket file.
+ if {![start_kerberos_daemons 0] \
+ || ![add_kerberos_key host/$hostname 0] \
+ || ![setup_srvtab 0] \
+ || ![add_kerberos_key $env(USER) 0] \
+ || ![kinit $env(USER) $env(USER)$KEY 0]} {
+ return
+ }
+
+ # Start up the telnet daemon.
+ start_telnet_daemon
+
+ # Start up our telnet connection. We first try it without
+ # authentication, so the daemon should prompt for a login.
+ spawn $TELNET -- $hostname -[expr 8 + $portbase]
+ set telnet_pid [exp_pid]
+
+ expect_after {
+ timeout {
+ fail "$testname (timeout)"
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ catch "expect_after"
+ return
+ }
+ }
+
+ set testname "simple telnet"
+ expect {
+ "ogin: " {
+ pass $testname
+ }
+ }
+
+ # Move back to telnet command mode and make sure it seems
+ # reasonable.
+ set testname "telnet command mode"
+ send "\035"
+ expect {
+ "telnet> " {
+ pass $testname
+ }
+ }
+
+ set testname "telnet status"
+ send "status\r"
+ # use -nocase because telnet may output the fqdn in upper-case;
+ # however, -nocase requires the whole pattern to be in lower case
+ expect {
+ -nocase -re "connected to $localhostname.*operating in single character mode.*catching signals locally.*remote character echo.*flow control.*escape character is '.\]'" {
+ pass $testname
+ }
+ }
+
+ set testname "back to command mode"
+
+ # For some reason, the telnet client doesn't necessarily reset the
+ # terminal mode back to raw after exiting command mode.
+ # Kick it somewhat by sending a CR.
+ send "\r"
+ expect "ogin: "
+
+ send "\035"
+ expect {
+ "telnet> " {
+ pass $testname
+ }
+ }
+
+ set testname "quit"
+ send "quit\r"
+ expect {
+ "Connection closed.\r" {
+ pass $testname
+ }
+ }
+
+ expect_after
+
+# on hpux 10.x, the child telnet will hang in an ioctl(). This will
+# wait a while for an EOF, and kill the process if it doesn't exit by
+# itself. The hang doesn't happen when telnet is run at the shell.
+
+ expect {
+ eof { }
+ timeout {
+ stop_telnet_daemon
+ }
+ }
+
+ if ![check_exit_status "exit status"] {
+ return
+ }
+
+ pass "exit status"
+
+ # The telnet daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_telnet_daemon
+
+ # Try an authenticated connection.
+ start_telnet_daemon
+ spawn $TELNET -a -k $REALMNAME -- $hostname -[expr 8 + $portbase]
+
+ expect_after {
+ timeout {
+ fail "$testname (timeout)"
+ catch "expect_after"
+ return
+ }
+ "Connection closed by foreign host.\r" {
+ fail "$testname (connection closed)"
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ catch "expect_after"
+ return
+ }
+ }
+
+ set testname "authenticated telnet"
+ expect "Kerberos V5 accepts you"
+ expect {
+ -re "$SHELL_PROMPT" {
+ pass $testname
+ }
+ }
+
+ # Switch to /bin/sh to try to avoid confusion from the shell
+ # prompt.
+ set testname "shell"
+ send "$BINSH\r"
+ expect -re "$SHELL_PROMPT"
+
+ set testname "date"
+ send "date\r"
+ expect "date"
+ expect {
+ -re "\[A-Za-z0-9 :\]+\[\r\n\]+" {
+ if [check_date $expect_out(0,string)] {
+ pass "date"
+ } else {
+ fail "date"
+ }
+ }
+ }
+ expect -re "$SHELL_PROMPT"
+
+ set testname "exit"
+ send "exit\r"
+ expect -re "$SHELL_PROMPT"
+ send "exit\r"
+ expect {
+ "Connection closed by foreign host.\r" {
+ pass $testname
+ }
+ }
+
+ expect_after
+ catch "expect eof"
+
+ # We can't use check_exit_status, because we expect an exit status
+ # of 1.
+ set status_list [wait -i $spawn_id]
+ verbose "wait -i $spawn_id returned $status_list (klist)"
+ if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 1 } {
+ send_log "exit status: $status_list\n"
+ verbose "exit status: $status_list"
+ fail "exit status"
+ } else {
+ pass "exit status"
+ }
+
+ # The telnet daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_telnet_daemon
+
+ # Try an authenticated encrypted connection.
+ start_telnet_daemon
+ spawn $TELNET -a -x -k $REALMNAME -- $hostname -[expr 8 + $portbase]
+
+ expect_after {
+ timeout {
+ fail $testname
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail $testname
+ catch "expect_after"
+ return
+ }
+ }
+
+ set testname "encrypted telnet"
+ expect "Kerberos V5 accepts you"
+ expect {
+ -re "$SHELL_PROMPT" {
+ pass $testname
+ }
+ }
+
+ # Make sure the encryption is not destroying the text.
+ set testname "echo"
+ send "echo hello\r"
+ expect "echo hello"
+ expect "hello"
+ expect {
+ -re "$SHELL_PROMPT" {
+ pass $testname
+ }
+ }
+
+ # Move back to telnet command mode and check the encryption status.
+ set testname "encryption status"
+ send "\035"
+ expect "telnet> "
+ send "status\r"
+ expect {
+ -re "Currently encrypting output with DES_CFB64.*Currently decrypting input with DES_CFB64" {
+ pass $testname
+ }
+ }
+
+ set testname "exit status"
+ send "exit\r"
+ expect "Connection closed by foreign host.\r"
+
+ expect_after
+ catch "expect eof"
+
+ # We can't use check_exit_status, because we expect an exit status
+ # of 1.
+ set status_list [wait -i $spawn_id]
+ verbose "wait -i $spawn_id returned $status_list (klist)"
+ if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 1 } {
+ send_log "exit status: $status_list\n"
+ verbose "exit status: $status_list"
+ fail "exit status"
+ } else {
+ pass "exit status"
+ }
+
+ # The telnet daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_telnet_daemon
+
+ set testname "reject unencrypted telnet"
+ # Check rejection of unencrypted client when encryption is required
+ start_telnet_daemon -e
+
+ # unencrypted, unauthenticated
+ spawn $TELNET -- $hostname -[expr 8 + $portbase]
+ expect_after {
+ timeout {
+ fail $testname
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail $testname
+ catch "expect_after"
+ return
+ }
+ }
+
+ expect {
+ -re "Unencrypted connection refused.*\n" {
+ pass $testname
+ }
+ }
+ catch "expect_after"
+ catch "expect eof"
+ catch wait
+
+ # The telnet daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_telnet_daemon
+}
+
+run_once telnet {
+ # Remove old wrapper script
+ catch "exec rm -f $tmppwd/login.wrap"
+
+ # Start up a root shell.
+ if ![setup_root_shell telnet] {
+ return
+ }
+
+ # Make sure .k5login is reasonable.
+ if ![check_k5login rlogin] {
+ stop_root_shell
+ return
+ }
+
+ # Set up the kerberos database.
+ if {![get_hostname] \
+ || ![setup_kerberos_files] \
+ || ![setup_kerberos_env] \
+ || ![setup_kerberos_db 0]} {
+ stop_root_shell
+ return
+ }
+
+ # Run the test. Logging in sometimes takes a while, so increase the
+ # timeout.
+ set oldtimeout $timeout
+ set timeout 60
+ set status [catch telnet_test msg]
+ set timeout $oldtimeout
+
+ # Shut down the kerberos daemons, the telnet daemon, and the rlogin
+ # process.
+ stop_kerberos_daemons
+
+ stop_telnet_daemon
+
+ stop_root_shell
+
+ if { $status != 0 } {
+ send_error "ERROR: error in telnet.exp\n"
+ send_error "$msg\n"
+ exit 1
+ }
+}
Added: trunk/tests/krb-standalone/gssftp.exp
===================================================================
--- trunk/tests/krb-standalone/gssftp.exp 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/krb-standalone/gssftp.exp 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,507 @@
+# Kerberos ftp test.
+# This is a DejaGnu test script.
+# This script tests Kerberos ftp.
+# Originally written by Ian Lance Taylor, Cygnus Support, <ian at cygnus.com>.
+# Modified bye Ezra Peisach for GSSAPI support.
+
+# Find the programs we need. We use the binaries from the build tree
+# if they exist. If they do not, then they must be in PATH. We
+# expect $objdir to be .../kerberos/build/tests/dejagnu
+
+if ![info exists FTP] {
+ set FTP [findfile $objdir/../gssftp/ftp/ftp]
+}
+
+if ![info exists FTPD] {
+ set FTPD [findfile $objdir/../gssftp/ftpd/ftpd]
+}
+
+# A procedure to start up the ftp daemon.
+
+proc start_ftp_daemon { } {
+ global FTPD
+ global tmppwd
+ global ftpd_spawn_id
+ global ftpd_pid
+ global portbase
+
+ # The -p argument tells it to accept a single connection, so we
+ # don't need to use inetd. Portbase+8 is the port to listen at.
+ # We rely on KRB5_KTNAME being set to the proper keyfile as there is
+ # no way to cleanly set it with the gssapi API.
+ # The -U argument tells it to use an alternate ftpusers file (using
+ # /dev/null will allow root to login regardless of /etc/ftpusers).
+ # The -a argument requires authorization, to mitigate any
+ # vulnerability introduced by circumventing ftpusers.
+ spawn $FTPD -p [expr 8 + $portbase] -a -U /dev/null -r $tmppwd/krb5.conf
+ set ftpd_spawn_id $spawn_id
+ set ftpd_pid [exp_pid]
+
+ # Give the ftp daemon a few seconds to get set up.
+ sleep 2
+}
+
+# A procedure to stop the ftp daemon.
+
+proc stop_ftp_daemon { } {
+ global ftpd_spawn_id
+ global ftpd_pid
+
+ if [info exists ftpd_pid] {
+ catch "close -i $ftpd_spawn_id"
+ catch "exec kill $ftpd_pid"
+ catch "wait -i $ftpd_spawn_id"
+ unset ftpd_pid
+ }
+}
+
+# Test that a file was copied correctly.
+proc check_file { filename {bigfile 0}} {
+ if ![file exists $filename] {
+ verbose "$filename does not exist"
+ send_log "$filename does not exist\n"
+ return 0
+ }
+
+ set file [open $filename r]
+ if { [gets $file line] == -1 } {
+ verbose "$filename is empty"
+ send_log "$filename is empty\n"
+ close $file
+ return 0
+ }
+
+ if ![string match "This file is used for ftp testing." $line] {
+ verbose "$filename contains $line"
+ send_log "$filename contains $line\n"
+ close $file
+ return 0
+ }
+
+ if {$bigfile} {
+ # + 1 for the newline
+ seek $file 1048577 current
+ if { [gets $file line] == -1 } {
+ verbose "$filename is truncated"
+ send_log "$filename is truncated\n"
+ close $file
+ return 0
+ }
+
+ if ![string match "This file is used for ftp testing." $line] {
+ verbose "$filename contains $line"
+ send_log "$filename contains $line\n"
+ close $file
+ return 0
+ }
+ }
+
+ if { [gets $file line] != -1} {
+ verbose "$filename is too long ($line)"
+ send_log "$filename is too long ($line)\n"
+ close $file
+ return 0
+ }
+
+ close $file
+
+ return 1
+}
+
+#
+# Restore environment variables possibly set.
+#
+proc ftp_restore_env { } {
+ global env
+ global ftp_save_ktname
+
+ catch "unset env(KRB5_KTNAME)"
+ if [info exists ftp_save_ktname] {
+ set env(KRB5_KTNAME) $ftp_save_ktname
+ unset ftp_save_ktname
+ }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc ftp_test { } {
+ global FTP
+ global KEY
+ global REALMNAME
+ global hostname
+ global localhostname
+ global env
+ global ftpd_spawn_id
+ global ftpd_pid
+ global spawn_id
+ global tmppwd
+ global ftp_save_ktname
+ global portbase
+
+ # Start up the kerberos and kadmind daemons and get a srvtab and a
+ # ticket file.
+ if {![start_kerberos_daemons 0] \
+ || ![add_random_key ftp/$hostname 0] \
+ || ![modify_principal ftp/$hostname -kvno 254] \
+ || ![setup_srvtab 0 ftp] \
+ || ![xst $tmppwd/srvtab ftp/$hostname]
+ || ![xst $tmppwd/srvtab ftp/$hostname]
+ || ![xst $tmppwd/srvtab ftp/$hostname]
+ || ![do_klist_kt $tmppwd/srvtab "gssftp keytab list"]
+ || ![add_kerberos_key $env(USER) 0] \
+ || ![kinit $env(USER) $env(USER)$KEY 0]} {
+ return
+ }
+ # Force the host key to exist, so we get consistent errors below.
+ catch "add_random_key host/$hostname 0"
+
+ #
+ # Save settings of KRB5_KTNAME
+ #
+ if [info exists env(KRB5_KTNAME)] {
+ set ftp_save_ktname $env(KRB5_KTNAME)
+ }
+
+ #
+ # set KRB5_KTNAME *incorrectly*
+ #
+ set env(KRB5_KTNAME) FILE:$tmppwd/srvtabxx
+ verbose "KRB5_KTNAME=$env(KRB5_KTNAME)"
+
+ # Force some auth errors.
+ set testname "ftp auth errors"
+
+ # Start the ftp daemon.
+ start_ftp_daemon
+
+ # Try connecting.
+ spawn $FTP -d -v $hostname [expr 8 + $portbase]
+ expect_after {
+ -re "--->\[^\r\n\]*\r\n" { exp_continue }
+ -re "encoding \[0-9\]* bytes MIC \[a-zA-Z0-9/+=\]*\r\n" { exp_continue }
+ -re "sealed \[A-Z()\]*" { exp_continue }
+ -re "secure_command\[A-Z()\]*" { exp_continue }
+ timeout {
+ fail "$testname (timeout)"
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ catch "expect_after"
+ return
+ }
+ }
+ expect -nocase "connected to $hostname"
+ expect -nocase -re "$localhostname.*ftp server .version \[0-9.\]*. ready."
+ expect -re "Using authentication type GSSAPI; ADAT must follow"
+ expect "GSSAPI accepted as authentication type"
+ expect -re "Trying to authenticate to <ftp at .*>"
+ # The ftp client doesn't print the gssapi error except on the last attempt.
+# expect "GSSAPI error major: Unspecified GSS failure."
+# expect -re "GSSAPI error minor: Key table file '.*' not found"
+ expect -re "Trying to authenticate to <host at .*>"
+ expect "GSSAPI error major: Unspecified GSS failure."
+ expect -re "GSSAPI error minor: Key table file '.*' not found"
+ expect -re "Name (.*): "
+ close -i $spawn_id
+ wait -i $spawn_id
+ wait -i $ftpd_spawn_id
+ catch "close -i $ftpd_spawn_id"
+
+ #
+ # set KRB5_KTNAME correctly now
+ #
+ set env(KRB5_KTNAME) FILE:$tmppwd/srvtab
+ verbose "KRB5_KTNAME=$env(KRB5_KTNAME)"
+
+ # Start the ftp daemon.
+ start_ftp_daemon
+
+ # Make an ftp client connection to it.
+ spawn $FTP -d -v $hostname [expr 8 + $portbase]
+
+ expect_after {
+ "GSSAPI authentication failed" {
+ fail "$testname (auth failed)"
+ catch "expect_after"
+ return
+ }
+ -re "--->\[^\r\n\]*\r\n" { exp_continue }
+ -re "encoding \[0-9\]* bytes MIC \[a-zA-Z0-9/+=\]*\r\n" { exp_continue }
+ -re "sealed \[A-Z()\]*" { exp_continue }
+ -re "secure_command\[A-Z()\]*" { exp_continue }
+ timeout {
+ fail "$testname (timeout)"
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ catch "expect_after"
+ return
+ }
+ }
+
+ set testname "ftp connection"
+ expect -nocase "connected to $hostname"
+ expect -nocase -re "$localhostname.*ftp server .version \[0-9.\]*. ready."
+ expect -re "Using authentication type GSSAPI; ADAT must follow"
+ expect "GSSAPI accepted as authentication type"
+ expect {
+ "GSSAPI authentication succeeded" { pass "ftp authentication" }
+ eof { fail "ftp authentication" ; catch "expect_after" ; return }
+ }
+ expect -nocase "name ($hostname:$env(USER)): "
+ send "$env(USER)\r"
+ expect "GSSAPI user $env(USER)@$REALMNAME is authorized as $env(USER)"
+ expect "Remote system type is UNIX."
+ expect "Using binary mode to transfer files."
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "binary"
+ send "binary\r"
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "status"
+ send "status\r"
+ expect -nocase "connected to $hostname."
+ expect "Authentication type: GSSAPI"
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "ls"
+ send "ls $tmppwd/ftp-test\r"
+ expect -re "Opening ASCII mode data connection for .*ls."
+ expect -re ".* $tmppwd/ftp-test"
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "nlist"
+ send "nlist $tmppwd/ftp-test\r"
+ expect -re "Opening ASCII mode data connection for file list."
+ expect -re "$tmppwd/ftp-test"
+ expect -re ".* Transfer complete."
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "ls missing"
+ send "ls $tmppwd/ftp-testmiss\r"
+ expect -re "Opening ASCII mode data connection for .*ls."
+ expect {
+ -re "$tmppwd/ftp-testmiss not found" {}
+ -re "$tmppwd/ftp-testmiss: No such file or directory"
+ }
+ expect "ftp> " {
+ pass $testname
+ }
+
+
+ set testname "get"
+ catch "exec rm -f $tmppwd/copy"
+ send "get $tmppwd/ftp-test $tmppwd/copy\r"
+ expect "Opening BINARY mode data connection for $tmppwd/ftp-test"
+ expect "Transfer complete"
+ expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+ expect "ftp> "
+ if [check_file $tmppwd/copy] {
+ pass $testname
+ } else {
+ fail $testname
+ }
+
+ set testname "put"
+ catch "exec rm -f $tmppwd/copy"
+ send "put $tmppwd/ftp-test $tmppwd/copy\r"
+ expect "Opening BINARY mode data connection for $tmppwd/copy"
+ expect "Transfer complete"
+ expect -re "\[0-9\]+ bytes sent in \[0-9.e-\]+ seconds"
+ expect "ftp> "
+ if [check_file $tmppwd/copy] {
+ pass $testname
+ } else {
+ fail $testname
+ }
+
+ set testname "cd"
+ send "cd $tmppwd\r"
+ expect "CWD command successful."
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "lcd"
+ send "lcd $tmppwd\r"
+ expect "Local directory now $tmppwd"
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "local get"
+ catch "exec rm -f $tmppwd/copy"
+ send "get ftp-test copy\r"
+ expect "Opening BINARY mode data connection for ftp-test"
+ expect "Transfer complete"
+ expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+ expect "ftp> "
+ if [check_file $tmppwd/copy] {
+ pass $testname
+ } else {
+ fail $testname
+ }
+
+ set testname "big local get"
+ catch "exec rm -f $tmppwd/copy"
+ send "get bigftp-test copy\r"
+ expect "Opening BINARY mode data connection for bigftp-test"
+ expect "Transfer complete"
+ expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+ expect "ftp> "
+ if [check_file $tmppwd/copy 1] {
+ pass $testname
+ } else {
+ fail $testname
+ }
+
+ set testname "start encryption"
+ send "private\r"
+ expect "Data channel protection level set to private"
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "status"
+ send "status\r"
+ expect "Protection Level: private"
+ expect "ftp> " {
+ pass $testname
+ }
+
+ set testname "encrypted get"
+ catch "exec rm -f $tmppwd/copy"
+ send "get ftp-test copy\r"
+ expect "Opening BINARY mode data connection for ftp-test"
+ expect "Transfer complete"
+ expect -re "\[0-9\]+ bytes received in \[0-9.e-\]+ seconds"
+ expect "ftp> "
+ if [check_file $tmppwd/copy] {
+ pass $testname
+ } else {
+ fail $testname
+ }
+
+ set testname "big encrypted get"
+ catch "exec rm -f $tmppwd/copy"
+ send "get bigftp-test copy\r"
+ expect "Opening BINARY mode data connection for bigftp-test"
+ expect {
+ -timeout 300
+ "Transfer complete" {}
+ -re "Length .* of PROT buffer > PBSZ" {
+ fail "$testname (PBSZ)"
+ return 0
+ }
+ }
+ expect -re "\[0-9\]+ bytes received in \[0-9.e+-\]+ seconds"
+ expect "ftp> "
+ if [check_file $tmppwd/copy 1] {
+ pass $testname
+ } else {
+ fail $testname
+ }
+
+ set testname "close"
+ send "close\r"
+ expect "Goodbye."
+ expect "ftp> "
+ set status_list [wait -i $ftpd_spawn_id]
+ verbose "wait -i $ftpd_spawn_id returned $status_list ($testname)"
+ catch "close -i $ftpd_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 $testname
+ } else {
+ pass $testname
+ unset ftpd_pid
+ }
+
+ set testname "quit"
+ send "quit\r"
+ expect_after
+ expect eof
+ if [check_exit_status $testname] {
+ pass $testname
+ }
+}
+
+run_once gssftp {
+ # Make sure .klogin is reasonable.
+ if ![check_k5login ftp] {
+ return
+ }
+
+ # Set up the kerberos database.
+ if {![get_hostname] \
+ || ![setup_kerberos_files] \
+ || ![setup_kerberos_env] \
+ || ![setup_kerberos_db 0]} {
+ return
+ }
+
+ # Create a file to use for ftp testing.
+ set file [open $tmppwd/ftp-test w]
+ puts $file "This file is used for ftp testing."
+ close $file
+
+ # Create a large file to use for ftp testing. File needs to be
+ # larger that 2^20 or 1MB for PBSZ testing.
+ set file [open $tmppwd/bigftp-test w]
+ puts $file "This file is used for ftp testing.\n"
+ seek $file 1048576 current
+ puts $file "This file is used for ftp testing."
+ close $file
+
+ # The ftp client will look in $HOME/.netrc for the user name to use.
+ # To avoid confusing the testsuite, point $HOME at a directory where
+ # we know there is no .netrc file.
+ if [info exists env(HOME)] {
+ set home $env(HOME)
+ } elseif [info exists home] {
+ unset home
+ }
+ set env(HOME) $tmppwd
+
+ # Run the test. Logging in sometimes takes a while, so increase the
+ # timeout.
+ set oldtimeout $timeout
+ set timeout 60
+ set status [catch ftp_test msg]
+ set timeout $oldtimeout
+
+ # Shut down the kerberos daemons and the ftp daemon.
+ stop_kerberos_daemons
+
+ stop_ftp_daemon
+
+ ftp_restore_env
+
+ # Reset $HOME, for safety in case we are going to run more tests.
+ if [info exists home] {
+ set env(HOME) $home
+ } else {
+ unset env(HOME)
+ }
+
+ if { $status != 0 } {
+ perror "error in gssftp.exp: $msg"
+ }
+}
Added: trunk/tests/krb-standalone/rcp.exp
===================================================================
--- trunk/tests/krb-standalone/rcp.exp 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/krb-standalone/rcp.exp 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,231 @@
+# Kerberos rcp test.
+# This is a DejaGnu test script.
+# This script tests Kerberos rcp.
+# Written by Ian Lance Taylor, Cygnus Support, <ian at cygnus.com>.
+
+# Find the programs we need. We use the binaries from the build tree
+# if they exist. If they do not, then they must be in PATH. We
+# expect $objdir to be .../kerberos/src.
+
+if ![info exists RCP] {
+ set RCP [findfile $objdir/../bsd/rcp]
+}
+
+if ![info exists KRSHD] {
+ set KRSHD [findfile $objdir/../bsd/kshd]
+}
+
+# Remove old wrapper script
+ catch "exec rm -f $tmppwd/rcp"
+
+# Make sure .k5login is reasonable.
+if ![check_k5login rcp] {
+ return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+ || ![setup_kerberos_files] \
+ || ![setup_kerberos_env] \
+ || ![setup_kerberos_db 0]} {
+ return
+}
+
+# A procedure to start up the rsh daemon (rcp talks to the rsh
+# daemon).
+
+proc start_rsh_daemon { } {
+ global REALMNAME
+ global KRSHD T_INETD
+ global RCP
+ global tmppwd
+ global krshd_spawn_id
+ global krshd_pid
+ global portbase
+
+ # Setup the shared library wrapper for login.krb5
+ if ![file exists $tmppwd/rcp] {
+ setup_wrapper $tmppwd/rcp "$RCP $*"
+ }
+
+
+ # The -L ENV_SET is for the I/S Athena brokeness in dot files where
+ # LD_LIBRARY_PATH will be overridden causing the "exec csh -c rcp ..."
+ # to fail as the .cshrc is read in. We do not use the -f option as
+ # a users shell might be sh...
+ # Later a proper fix would be to have kshd exec rcp directly
+ # shell indirection...
+ spawn $T_INETD [expr 8 + $portbase] $KRSHD $KRSHD -k -c -P $tmppwd -S $tmppwd/srvtab -M $REALMNAME -L ENV_SET
+ set krshd_spawn_id $spawn_id
+ set krshd_pid [exp_pid]
+
+ expect {
+ -ex "Ready!" { }
+ eof { error "couldn't start t_inetd helper" }
+ }
+}
+
+# A procedure to stop the rsh daemon.
+
+proc stop_rsh_daemon { } {
+ global krshd_spawn_id
+ global krshd_pid
+
+ if [info exists krshd_pid] {
+ catch "exec kill $krshd_pid"
+ catch {
+ expect {
+ -i $krshd_spawn_id
+ -re ..* { exp_continue }
+ eof {}
+ }
+ }
+ catch "close -i $krshd_spawn_id"
+ catch "wait -i $krshd_spawn_id"
+ unset krshd_pid
+ }
+}
+
+# Create a file to use for rcp testing.
+set file [open $tmppwd/rcp-test w]
+puts $file "This file is used for rcp testing."
+close $file
+
+# Test that a file was copied correctly.
+proc check_file { filename } {
+ if ![file exists $filename] {
+ verbose "$filename does not exist"
+ send_log "$filename does not exist\n"
+ return 0
+ }
+
+ set file [open $filename r]
+ if { [gets $file line] == -1 } {
+ verbose "$filename is empty"
+ send_log "$filename is empty\n"
+ close $file
+ return 0
+ }
+
+ if ![string match "This file is used for rcp testing." $line] {
+ verbose "$filename contains $line"
+ send_log "$filename contains $line\n"
+ close $file
+ return 0
+ }
+
+ if { [gets $file line] != -1} {
+ verbose "$filename is too long ($line)"
+ send_log "$filename is too long ($line)\n"
+ close $file
+ return 0
+ }
+
+ close $file
+
+ return 1
+}
+
+# Test copying one file to another.
+proc rcp_one_test { testname options frompref topref } {
+ global REALMNAME
+ global RCP
+ global tmppwd
+ global portbase
+
+ send_log "rm -f $tmppwd/copy\n"
+ verbose "exec rm -f $tmppwd/copy"
+ catch "exec rm -f $tmppwd/copy"
+
+ set from [format "%s%s" $frompref $tmppwd/rcp-test]
+ set to [format "%s%s" $topref $tmppwd/copy]
+
+ send_log "$RCP $options -D [expr 8 + $portbase] -N -k $REALMNAME $from $to\n"
+ verbose "$RCP $options -D [expr 8 + $portbase] -N -k $REALMNAME $from $to"
+ catch "exec $RCP $options -D [expr 8 + $portbase] -N -k $REALMNAME $from $to" exec_output
+
+ if ![string match "" $exec_output] {
+ send_log "$exec_output\n"
+ verbose "$exec_output"
+ fail $testname
+ return 0
+ }
+
+ if ![check_file $tmppwd/copy] {
+ fail $testname
+ return 0
+ }
+
+ pass $testname
+
+ return 1
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc rcp_test { } {
+ global RCP
+ global KEY
+ global hostname
+ global hostname
+ global env
+
+ # Start up the kerberos and kadmind daemons and get a srvtab and a
+ # ticket file.
+ if {![start_kerberos_daemons 0] \
+ || ![add_kerberos_key host/$hostname 0] \
+ || ![setup_srvtab 0] \
+ || ![add_kerberos_key $env(USER) 0] \
+ || ![kinit $env(USER) $env(USER)$KEY 0]} {
+ return
+ }
+
+ rcp_one_test "local rcp" "" "" ""
+
+ start_rsh_daemon
+ rcp_one_test "rcp from" "" "$hostname:" ""
+ stop_rsh_daemon
+
+ start_rsh_daemon
+ rcp_one_test "rcp to" "" "" "$hostname:"
+ stop_rsh_daemon
+
+ # Doing rcp between two hosts actually just executes rsh rcp on
+ # the source. We could test this, but we're not set up for it
+ # right now. Also, it's pretty much covered by the other rcp
+ # tests and by the rsh tests.
+ # start_rsh_daemon
+ # rcp_one_test "rcp between" "" "$hostname:" "$hostname:"
+ # stop_rsh_daemon
+
+ start_rsh_daemon
+ rcp_one_test "encrypted rcp from" "-x -c $env(KRB5CCNAME) -C $env(KRB5_CONFIG)" "$hostname:" ""
+ stop_rsh_daemon
+
+ start_rsh_daemon
+ rcp_one_test "encrypted rcp to" "-x -c $env(KRB5CCNAME) -C $env(KRB5_CONFIG)" "" "$hostname:"
+ stop_rsh_daemon
+
+ # Doing rcp between two hosts actually just executes rsh rcp on
+ # the source. We could test this, but we're not set up for it
+ # right now. Also, it's pretty much covered by the other rcp
+ # tests and by the rsh tests.
+ # start_rsh_daemon
+ # rcp_one_test "encrypted rcp between" "-x" "$hostname:" "$hostname:"
+ # stop_rsh_daemon
+}
+
+# Run the test.
+set status [catch rcp_test msg]
+
+# Shut down the kerberos daemons and the rsh daemon.
+stop_kerberos_daemons
+
+stop_rsh_daemon
+
+if { $status != 0 } {
+ send_error "ERROR: error in rcp.exp\n"
+ send_error "$msg\n"
+ exit 1
+}
Added: trunk/tests/krb-standalone/rsh.exp
===================================================================
--- trunk/tests/krb-standalone/rsh.exp 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/krb-standalone/rsh.exp 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,290 @@
+# Kerberos rsh test.
+# This is a DejaGnu test script.
+# This script tests Kerberos rsh.
+# Written by Ian Lance Taylor, Cygnus Support, <ian at cygnus.com>.
+
+# Find the programs we need. We use the binaries from the build tree
+# if they exist. If they do not, then they must be in PATH. We
+# expect $objdir to be .../kerberos/src.
+
+if ![info exists RSH] {
+ set RSH [findfile $objdir/../bsd/rsh]
+}
+
+if ![info exists KRSHD] {
+ set KRSHD [findfile $objdir/../bsd/kshd]
+}
+
+# Make sure .k5login is reasonable.
+if ![check_k5login rsh] {
+ return
+}
+
+# Set up the kerberos database.
+if {![get_hostname] \
+ || ![setup_kerberos_files] \
+ || ![setup_kerberos_db 0]} {
+ return
+}
+
+# A procedure to start up the rsh daemon.
+
+proc start_rsh_daemon { option } {
+ global REALMNAME
+ global KRSHD T_INETD
+ global tmppwd
+ global krshd_spawn_id
+ global krshd_pid
+ global portbase
+
+ spawn $T_INETD [expr 8 + $portbase] $KRSHD $KRSHD -k -c -S $tmppwd/srvtab -M $REALMNAME -A $option
+ set krshd_spawn_id $spawn_id
+ set krshd_pid [exp_pid]
+
+ expect {
+ -ex "Ready!" { }
+ eof { error "couldn't start t_inetd helper" }
+ }
+}
+
+# A procedure to stop the rsh daemon.
+
+proc stop_rsh_daemon { } {
+ global krshd_spawn_id
+ global krshd_pid
+
+ if [info exists krshd_pid] {
+ catch "exec kill $krshd_pid"
+ catch {
+ expect {
+ -i $krshd_spawn_id
+ -re ..* { exp_continue }
+ eof {}
+ }
+ }
+ catch "close -i $krshd_spawn_id"
+ catch "wait -i $krshd_spawn_id"
+ unset krshd_pid
+ }
+}
+
+# Wrap the tests in a procedure, so that we can kill the daemons if
+# we get some sort of error.
+
+proc rsh_test { } {
+ global REALMNAME
+ global KLIST
+ global RSH
+ global KEY
+ global BINSH
+ global hostname
+ global env
+ global spawn_id
+ global tmppwd
+ global portbase
+
+ # Start up the kerberos and kadmind daemons and get a srvtab and a
+ # ticket file.
+ if {![start_kerberos_daemons 0] \
+ || ![add_kerberos_key host/$hostname 0] \
+ || ![setup_srvtab 0] \
+ || ![add_kerberos_key $env(USER) 0] \
+ || ![setup_kerberos_env client] \
+ || ![kinit $env(USER) $env(USER)$KEY 0]} {
+ return
+ }
+
+ # Start up the rsh daemon.
+ start_rsh_daemon -k
+
+ # Run rsh date.
+ set testname "date"
+ spawn $RSH $hostname -k $REALMNAME -D [expr 8 + $portbase] -A date
+ expect {
+ -re "\[A-Za-z0-9\]+ \[A-Za-z0-9\]+ +\[0-9\]+ \[0-9\]+:\[0-9\]+:\[0-9\]+ \[A-Za-z0-9\]+ \[0-9\]+\r\n" {
+ set result $expect_out(0,string)
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ return
+ }
+ }
+ expect eof
+ if ![check_exit_status $testname] {
+ return
+ }
+
+ if [check_date $result] {
+ pass $testname
+ } else {
+ fail $testname
+ }
+
+ # The rsh daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_rsh_daemon
+
+ # Check encrypted rsh.
+ set failed no
+ start_rsh_daemon -ek
+ set testname "encrypted rsh"
+ spawn $RSH $hostname -x -k $REALMNAME -D [expr 8 + $portbase] -A echo hello
+ expect {
+ "hello" { expect eof }
+ timeout {
+ fail "$testname (timeout)"
+ set failed yes
+ }
+ eof {
+ fail "$testname (eof)"
+ set failed yes
+ }
+ }
+
+ catch "expect eof"
+ if { $failed == "no" } {
+ if ![check_exit_status $testname] {
+ return
+ }
+ pass $testname
+ stop_rsh_daemon
+ } else {
+ catch "wait -i $spawn_id"
+ catch "close -i $spawn_id"
+ stop_rsh_daemon
+ }
+
+ # Check ticket forwarding
+ set failed no
+ start_rsh_daemon -k
+ set testname "rsh forwarding tickets"
+
+ # We need a wrapper for klist in order to setup for shared library
+ # runtime environment
+ setup_wrapper $tmppwd/klist.wrap $KLIST
+
+ spawn $RSH $hostname -f -k $REALMNAME -D [expr 8 + $portbase] -A $BINSH -c $tmppwd/klist.wrap
+ expect {
+ "Ticket cache:*\r" {
+ expect eof
+ }
+ "klist: No credentials cache file found" {
+ fail "$testname (not forwarded)"
+ return
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ return
+ }
+ }
+
+ if ![check_exit_status $testname] {
+ return
+ }
+
+ pass $testname
+
+ stop_rsh_daemon
+
+ # Check encrypted ticket forwarding
+ set failed no
+ start_rsh_daemon -e
+ set testname "encrypted rsh forwarding tickets"
+ spawn $RSH $hostname -x -f -k $REALMNAME -D [expr 8 + $portbase] -A $BINSH -c $tmppwd/klist.wrap
+ expect {
+ "Ticket cache:*\r" {
+ expect eof
+ }
+ "klist: No credentials cache file found" {
+ fail "$testname (not forwarded)"
+ return
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ return
+ }
+ }
+
+ if ![check_exit_status $testname] {
+ return
+ }
+
+ pass $testname
+
+ stop_rsh_daemon
+
+ # Check stderr
+ start_rsh_daemon -k
+ set testname "rsh to stderr"
+ spawn $RSH $hostname -k $REALMNAME -D [expr 8 + $portbase] -A $BINSH -c "'echo hello 1>&2'"
+ expect {
+ "hello" { expect eof }
+ timeout {
+ fail "$testname (timeout)"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ return
+ }
+ }
+
+ if ![check_exit_status $testname] {
+ return
+ }
+
+ pass $testname
+
+ stop_rsh_daemon
+
+ start_rsh_daemon -e
+ set testname "encrypted rsh to stderr"
+ spawn $RSH $hostname -x -k $REALMNAME -D [expr 8 + $portbase] -A $BINSH -c "'echo hello 1>&2'"
+ expect {
+ "hello" { expect eof }
+ timeout {
+ fail "$testname (timeout)"
+ return
+ }
+ eof {
+ fail "$testname (eof)"
+ return
+ }
+ }
+
+ if ![check_exit_status $testname] {
+ return
+ }
+
+ pass $testname
+
+ # The rsh daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_rsh_daemon
+}
+
+# Run the test.
+set status [catch rsh_test msg]
+
+# Shut down the kerberos daemons and the rsh daemon.
+stop_kerberos_daemons
+
+stop_rsh_daemon
+
+if { $status != 0 } {
+ send_error "ERROR: error in rsh.exp\n"
+ send_error "$msg\n"
+ exit 1
+}
Added: trunk/tests/resolve/Makefile.in
===================================================================
--- trunk/tests/resolve/Makefile.in 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/resolve/Makefile.in 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,30 @@
+mydir=tests/resolve
+BUILDTOP=$(REL)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+OBJS=resolve.o addrinfo-test.o fake-addrinfo-test.o
+SRCS=$(srcdir)/resolve.c $(srcdir)/addrinfo-test.c \
+ $(srcdir)/fake-addrinfo-test.c
+
+all:: resolve addrinfo-test fake-addrinfo-test
+
+resolve: resolve.o
+ $(CC_LINK) -o $@ resolve.o $(LIBS)
+
+addrinfo-test: addrinfo-test.o
+ $(CC_LINK) -o $@ addrinfo-test.o $(KRB5_BASE_LIBS) $(LIBS)
+
+fake-addrinfo-test: fake-addrinfo-test.o
+ $(CC_LINK) -o $@ fake-addrinfo-test.o $(KRB5_BASE_LIBS) $(LIBS)
+
+check:: resolve addrinfo-test fake-addrinfo-test
+ $(VALGRIND) ./resolve
+ $(VALGRIND) ./addrinfo-test -p telnet
+ $(VALGRIND) ./fake-addrinfo-test -p telnet
+
+install::
+
+clean::
+ $(RM) resolve addrinfo-test fake-addrinfo-test
+
Added: trunk/tests/resolve/addrinfo-test.c
===================================================================
--- trunk/tests/resolve/addrinfo-test.c 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/resolve/addrinfo-test.c 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,316 @@
+/*
+ * test/resolve/addrinfo-test.c
+ *
+ * Copyright 2004 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * A simple program to test the functionality of the getaddrinfo function.
+ *
+ * Usage:
+ * addrinfo-test [-t|-u|-R|-I] [-d|-s|-r] [-p port] [-P] [hostname]
+ *
+ * When invoked with no arguments, NULL is used for the node name,
+ * which (at least with a non-null "port") means a socket address
+ * is desired that can be used with connect() or bind() (depending
+ * on whether "-P" is given).
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h> /* needed for IPPROTO_* on NetBSD */
+#include <k5-platform.h>
+#ifdef USE_FAKE_ADDRINFO
+#include "fake-addrinfo.h"
+#endif
+
+static const char *protoname (int p) {
+ static char buf[30];
+
+#define X(N) if (p == IPPROTO_ ## N) return #N
+
+ X(TCP);
+ X(UDP);
+ X(ICMP);
+#ifdef IPPROTO_IPV6
+ X(IPV6);
+#endif
+#ifdef IPPROTO_GRE
+ X(GRE);
+#endif
+#ifdef IPPROTO_NONE
+ X(NONE);
+#endif
+ X(RAW);
+#ifdef IPPROTO_COMP
+ X(COMP);
+#endif
+
+ snprintf(buf, sizeof(buf), " %-2d", p);
+ return buf;
+}
+
+static const char *socktypename (int t) {
+ static char buf[30];
+ switch (t) {
+ case SOCK_DGRAM: return "DGRAM";
+ case SOCK_STREAM: return "STREAM";
+ case SOCK_RAW: return "RAW";
+ case SOCK_RDM: return "RDM";
+ case SOCK_SEQPACKET: return "SEQPACKET";
+ }
+ snprintf(buf, sizeof(buf), " %-2d", t);
+ return buf;
+}
+
+static char *whoami;
+
+static void usage () {
+ fprintf(stderr,
+ "usage:\n"
+ "\t%s [ options ] [host]\n"
+ "options:\n"
+ "\t-t\tspecify protocol IPPROTO_TCP\n"
+ "\t-u\tspecify protocol IPPROTO_UDP\n"
+ "\t-R\tspecify protocol IPPROTO_RAW\n"
+ "\t-I\tspecify protocol IPPROTO_ICMP\n"
+ "\n"
+ "\t-d\tspecify socket type SOCK_DGRAM\n"
+ "\t-s\tspecify socket type SOCK_STREAM\n"
+ "\t-r\tspecify socket type SOCK_RAW\n"
+ "\n"
+ "\t-4\tspecify address family AF_INET\n"
+#ifdef AF_INET6
+ "\t-6\tspecify address family AF_INET6\n"
+#endif
+ "\n"
+ "\t-p P\tspecify port P (service name or port number)\n"
+ "\t-N\thostname is numeric, skip DNS query\n"
+ "\t-n\tservice/port is numeric (sets AI_NUMERICSERV)\n"
+ "\t-P\tset AI_PASSIVE\n"
+ "\n"
+ "default: protocol 0, socket type 0, address family 0, null port\n"
+ ,
+ whoami);
+ /* [ -t | -u | -R | -I ] [ -d | -s | -r ] [ -p port ] */
+ exit (1);
+}
+
+static const char *familyname (int f) {
+ static char buf[30];
+ switch (f) {
+ default:
+ snprintf(buf, sizeof(buf), "AF %d", f);
+ return buf;
+ case AF_INET: return "AF_INET";
+#ifdef AF_INET6
+ case AF_INET6: return "AF_INET6";
+#endif
+ }
+}
+
+#define eaistr(X) (X == EAI_SYSTEM ? strerror(errno) : gai_strerror(X))
+
+int main (int argc, char *argv[])
+{
+ struct addrinfo *ap, *ap2;
+ int err, numerichost = 0, numericserv = 0;
+ char *hname, *port = 0, *sep;
+ struct addrinfo hints;
+
+ whoami = strrchr(argv[0], '/');
+ if (whoami == 0)
+ whoami = argv[0];
+ else
+ whoami = whoami+1;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = 0;
+ hints.ai_socktype = 0;
+
+ hname = 0;
+ hints.ai_family = 0;
+
+ if (argc == 1)
+ usage ();
+
+ while (++argv, --argc > 0) {
+ char *arg;
+ arg = *argv;
+
+ if (*arg != '-')
+ hname = arg;
+ else if (arg[1] == 0 || arg[2] != 0)
+ usage ();
+ else
+ switch (arg[1]) {
+ case 'u':
+ hints.ai_protocol = IPPROTO_UDP;
+ break;
+ case 't':
+ hints.ai_protocol = IPPROTO_TCP;
+ break;
+ case 'R':
+ hints.ai_protocol = IPPROTO_RAW;
+ break;
+ case 'I':
+ hints.ai_protocol = IPPROTO_ICMP;
+ break;
+ case 'd':
+ hints.ai_socktype = SOCK_DGRAM;
+ break;
+ case 's':
+ hints.ai_socktype = SOCK_STREAM;
+ break;
+ case 'r':
+ hints.ai_socktype = SOCK_RAW;
+ break;
+ case 'p':
+ if (argv[1] == 0 || argv[1][0] == 0 || argv[1][0] == '-')
+ usage ();
+ port = argv[1];
+ argc--, argv++;
+ break;
+ case '4':
+ hints.ai_family = AF_INET;
+ break;
+#ifdef AF_INET6
+ case '6':
+ hints.ai_family = AF_INET6;
+ break;
+#endif
+ case 'N':
+ numerichost = 1;
+ break;
+ case 'n':
+ numericserv = 1;
+ break;
+ case 'P':
+ hints.ai_flags |= AI_PASSIVE;
+ break;
+ default:
+ usage ();
+ }
+ }
+
+ if (hname && !numerichost)
+ hints.ai_flags |= AI_CANONNAME;
+ if (numerichost) {
+#ifdef AI_NUMERICHOST
+ hints.ai_flags |= AI_NUMERICHOST;
+#else
+ fprintf(stderr, "AI_NUMERICHOST not defined on this platform\n");
+ exit(1);
+#endif
+ }
+ if (numericserv) {
+#ifdef AI_NUMERICSERV
+ hints.ai_flags |= AI_NUMERICSERV;
+#else
+ fprintf(stderr, "AI_NUMERICSERV not defined on this platform\n");
+ exit(1);
+#endif
+ }
+
+ printf("getaddrinfo(hostname %s, service %s,\n"
+ " hints { ",
+ hname ? hname : "(null)", port ? port : "(null)");
+ sep = "";
+#define Z(FLAG) if (hints.ai_flags & AI_##FLAG) printf("%s%s", sep, #FLAG), sep = "|"
+ Z(CANONNAME);
+ Z(PASSIVE);
+#ifdef AI_NUMERICHOST
+ Z(NUMERICHOST);
+#endif
+#ifdef AI_NUMERICSERV
+ Z(NUMERICSERV);
+#endif
+ if (sep[0] == 0)
+ printf ("no-flags");
+ if (hints.ai_family)
+ printf(" %s", familyname(hints.ai_family));
+ if (hints.ai_socktype)
+ printf(" SOCK_%s", socktypename(hints.ai_socktype));
+ if (hints.ai_protocol)
+ printf(" IPPROTO_%s", protoname(hints.ai_protocol));
+ printf(" }):\n");
+
+ err = getaddrinfo(hname, port, &hints, &ap);
+ if (err) {
+ printf("\terror => %s\n", eaistr(err));
+ return 1;
+ }
+
+#if defined(SIN6_LEN)
+ if (ap->ai_addr->sa_len == 0)
+ printf ("BAD: sa_len not set!\n");
+#endif
+
+
+ for (ap2 = ap; ap2; ap2 = ap2->ai_next) {
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+ /* If we don't do this, even AIX's own getnameinfo will reject
+ the sockaddr structures. The sa_len field doesn't get set
+ either, on AIX, but getnameinfo won't complain. */
+ if (ap2->ai_addr->sa_family == 0) {
+ printf("BAD: sa_family zero! fixing...\n");
+ ap2->ai_addr->sa_family = ap2->ai_family;
+ } else if (ap2->ai_addr->sa_family != ap2->ai_family) {
+ printf("BAD: sa_family != ai_family! fixing...\n");
+ ap2->ai_addr->sa_family = ap2->ai_family;
+ }
+ if (getnameinfo(ap2->ai_addr, ap2->ai_addrlen, hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
+ strlcpy(hbuf, "...", sizeof(hbuf));
+ strlcpy(pbuf, "...", sizeof(pbuf));
+ }
+ printf("%p:\n"
+ "\tfamily = %s\tproto = %-4s\tsocktype = %s\n",
+ ap2, familyname(ap2->ai_family),
+ protoname (ap2->ai_protocol),
+ socktypename (ap2->ai_socktype));
+ if (ap2->ai_canonname) {
+ if (ap2->ai_canonname[0])
+ printf("\tcanonname = %s\n", ap2->ai_canonname);
+ else
+ printf("BAD: ai_canonname is set but empty!\n");
+ } else if (ap2 == ap && (hints.ai_flags & AI_CANONNAME)) {
+ printf("BAD: first ai_canonname is null!\n");
+ }
+ printf("\taddr = %-28s\tport = %s\n", hbuf, pbuf);
+
+ err = getnameinfo(ap2->ai_addr, ap2->ai_addrlen, hbuf, sizeof (hbuf),
+ pbuf, sizeof(pbuf), NI_NAMEREQD);
+ if (err)
+ printf("\tgetnameinfo(NI_NAMEREQD): %s\n", eaistr(err));
+ else
+ printf("\tgetnameinfo => %s, %s\n", hbuf, pbuf);
+ }
+ freeaddrinfo(ap);
+ return 0;
+}
Added: trunk/tests/resolve/deps
===================================================================
--- trunk/tests/resolve/deps 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/resolve/deps 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,10 @@
+#
+# Generated makefile dependencies follow.
+#
+$(OUTPRE)resolve.$(OBJEXT): $(BUILDTOP)/autoconf.h \
+ resolve.c
+$(OUTPRE)addrinfo-test.$(OBJEXT): $(BUILDTOP)/autoconf.h \
+ $(SRCTOP)/k5-platform.h addrinfo-test.c
+$(OUTPRE)fake-addrinfo-test.$(OBJEXT): $(BUILDTOP)/autoconf.h \
+ $(SRCTOP)/fake-addrinfo.h $(SRCTOP)/k5-platform.h $(SRCTOP)/port-sockets.h \
+ $(SRCTOP)/socket-utils.h addrinfo-test.c fake-addrinfo-test.c
Added: trunk/tests/resolve/fake-addrinfo-test.c
===================================================================
--- trunk/tests/resolve/fake-addrinfo-test.c 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/resolve/fake-addrinfo-test.c 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,2 @@
+#define USE_FAKE_ADDRINFO
+#include "addrinfo-test.c"
Added: trunk/tests/resolve/resolve.c
===================================================================
--- trunk/tests/resolve/resolve.c 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/resolve/resolve.c 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,172 @@
+/*
+ * test/resolve/resolve.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * A simple program to test the functionality of the resolver library.
+ * It simply will try to get the IP address of the host, and then look
+ * up the name from the address. If the resulting name does not contain the
+ * domain name, then the resolve library is broken.
+ *
+ * Warning: It is possible to fool this program into thinking everything is
+ * alright byt a clever use of /etc/hosts - but this is better than nothing.
+ *
+ * Usage:
+ * resolve [hostname]
+ *
+ * When invoked with no arguments, gethostname is used for the local host.
+ *
+ */
+
+/* This program tests the resolve library and sees if it is broken... */
+
+#include "autoconf.h"
+#include <stdio.h>
+
+#if STDC_HEADERS
+#include <string.h>
+#else
+#ifndef HAVE_STRCHR
+#define strchr index
+#endif
+char *strchr();
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char myname[MAXHOSTNAMELEN+1];
+ char *ptr;
+ struct in_addr addrcopy;
+ struct hostent *host;
+ int quiet = 0;
+
+ argc--; argv++;
+ while (argc) {
+ if ((strcmp(*argv, "--quiet") == 0) ||
+ (strcmp(*argv, "-q") == 0)) {
+ quiet++;
+ } else
+ break;
+ argc--; argv++;
+ }
+
+ if (argc >= 1) {
+ strncpy(myname, *argv, MAXHOSTNAMELEN);
+ } else {
+ if(gethostname(myname, MAXHOSTNAMELEN)) {
+ perror("gethostname failure");
+ exit(1);
+ }
+ }
+
+ myname[MAXHOSTNAMELEN] = '\0'; /* for safety */
+
+ /* Look up the address... */
+ if (!quiet)
+ printf("Hostname: %s\n", myname);
+
+
+ /* Set the hosts db to close each time - effectively rewinding file */
+ sethostent(0);
+
+ if((host = gethostbyname (myname)) == NULL) {
+ fprintf(stderr,
+ "Could not look up address for hostname '%s' - fatal\n",
+ myname);
+ exit(2);
+ }
+
+ ptr = host->h_addr_list[0];
+#define UC(a) (((int)a)&0xff)
+ if (!quiet)
+ printf("Host address: %d.%d.%d.%d\n",
+ UC(ptr[0]), UC(ptr[1]), UC(ptr[2]), UC(ptr[3]));
+
+ memcpy(&addrcopy.s_addr, ptr, 4);
+
+ /* Convert back to full name */
+ if((host = gethostbyaddr(&addrcopy.s_addr, 4, AF_INET)) == NULL) {
+ fprintf(stderr, "Error looking up IP address - fatal\n");
+ exit(2);
+ }
+
+ if (quiet)
+ printf("%s\n", host->h_name);
+ else
+ printf("FQDN: %s\n", host->h_name);
+
+ /*
+ * The host name must have at least one '.' in the name, and
+ * if there is only one '.', it must not be at the end of the
+ * string. (i.e., "foo." is not a FQDN)
+ */
+ ptr = strchr(host->h_name, '.');
+ if (ptr == NULL || ptr[1] == '\0') {
+ fprintf(stderr,
+ "\nResolve library did not return a "
+ "fully qualified domain name.\n\n"
+ "If you are using /etc/hosts before DNS, "
+ "e.g. \"files\" is listed first\n"
+ "for \"hosts:\" in nsswitch.conf, ensure that "
+ "you have listed the FQDN\n"
+ "as the first name for the local host.\n\n"
+ "If this does not correct the problem, "
+ "you may have to reconfigure the kerberos\n"
+ "distribution to select a "
+ "different set of libraries using \n"
+ "--with-netlib[=libs]\n");
+ exit(3);
+ }
+
+ if (!quiet)
+ printf("Resolve library appears to have passed the test\n");
+
+ /* All ok */
+ exit(0);
+
+}
+
+
Added: trunk/tests/t_inetd.c
===================================================================
--- trunk/tests/t_inetd.c 2009-07-09 16:19:16 UTC (rev 3258)
+++ trunk/tests/t_inetd.c 2009-07-10 20:35:46 UTC (rev 3259)
@@ -0,0 +1,140 @@
+/*
+ * tests/dejagnu/t_inetd.c
+ *
+ * Copyright 1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * A simple program to simulate starting a process from inetd.
+ *
+ * Unlike a proper inetd situation, environment variables are passed
+ * to the client.
+ *
+ * usage: t_inetd port program argv0 ...
+ *
+ */
+
+#include "autoconf.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "com_err.h"
+
+
+char *progname;
+
+static void usage()
+{
+ fprintf(stderr, "%s: port program argv0 argv1 ...\n", progname);
+ exit(1);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ unsigned short port;
+ char *path;
+ int sock, acc;
+ int one = 1;
+ struct sockaddr_in l_inaddr, f_inaddr; /* local, foreign address */
+ int namelen = sizeof(f_inaddr);
+#ifdef POSIX_SIGNALS
+ struct sigaction csig;
+#endif
+
+ progname = argv[0];
+
+ if(argc <= 3) usage();
+
+ if(atoi(argv[1]) == 0) usage();
+
+ port = htons(atoi(argv[1]));
+ path = argv[2];
+
+ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+ com_err(progname, errno, "creating socket");
+ exit(3);
+ }
+
+ (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one,
+ sizeof (one));
+
+ l_inaddr.sin_family = AF_INET;
+ l_inaddr.sin_addr.s_addr = 0;
+ l_inaddr.sin_port = port;
+
+ if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) {
+ com_err(progname, errno, "binding socket");
+ exit(3);
+ }
+
+ if (listen(sock, 1) == -1) {
+ com_err(progname, errno, "listening");
+ exit(3);
+ }
+
+ printf("Ready!\n");
+ if ((acc = accept(sock, (struct sockaddr *)&f_inaddr,
+ &namelen)) == -1) {
+ com_err(progname, errno, "accepting");
+ exit(3);
+ }
+
+ dup2(acc, 0);
+ dup2(acc, 1);
+ dup2(acc, 2);
+ close(sock);
+ sock = 0;
+
+ /* Don't wait for a child signal... Otherwise dejagnu gets confused */
+#ifdef POSIX_SIGNALS
+ csig.sa_handler = (RETSIGTYPE (*)())0;
+ sigemptyset(&csig.sa_mask);
+ csig.sa_flags = 0;
+ sigaction(SIGCHLD, &csig, (struct sigaction *)0);
+#else
+ signal(SIGCHLD, SIG_IGN);
+#endif
+
+ if(execv(path, &argv[3]))
+ fprintf(stderr, "t_inetd: Could not exec %s\n", path);
+ exit(1);
+}
+
More information about the Krb5-appl-commits
mailing list