Robustness of tests and TFTP client.

Test coverage for IPv6, better shell portability,
and TFTP client robustness for single stacked hosts.
This commit is contained in:
Mats Erik Andersson
2012-01-31 00:33:42 +01:00
parent 17e24964ca
commit f5bef4df8f
5 changed files with 160 additions and 254 deletions

View File

@@ -1,3 +1,23 @@
2012-01-31 Mats Erik Andersson <gnu@gisladisker.se>
* src/tftp.c (resolve_name): Do not use AI_ADDRCONFIG at all.
Assign HOSTNAME with `ai->ai_canonname' only if it has contents,
otherwise assign `<dummy>', which is very unlikely.
* tests/ftp-localhost.sh: Make SVR4-compliant. Refactor code.
Error messages go to STDERR. Use HERE-docs for configuration.
(PWD): If not exported, assign with command substitution `pwd`.
(USER, FTPUSER, save_IFS): New variables.
(FTPHOME): New variable, for portably calculating home of FTPUSER.
Make certain of existence and readability of this directory.
(test_report): New function for common evaluation tasks.
* tests/syslogd.sh (PWD): If not exported, assign with command
substitution `pwd`.
* tests/tftp.sh: Expand to cover IPv6. Error messages to STDERR.
Make `inetd' and `tftp' verbose only with VERBOSE set.
(PWD): If not exported, assign with command substitution `pwd`.
(locate_port): New prototype, dropping address family argument,
always detecting IPv4 and IPv6.
2012-01-27 Mats Erik Andersson <gnu@gisladisker.se>
* libtelnet/auth.c, libtelnet/enc_des.c, libtelnet/encrypt.c,
@@ -22,6 +42,7 @@
* tests/ftp-localhost.sh, tests/tftp.sh (PORT): Detect if it
is preset, or detect an unused value from a short list.
* tests/ftp-localhost.sh (locate_port): New function.
2012-01-26 Mats Erik Andersson <gnu@gisladisker.se>

View File

@@ -303,9 +303,6 @@ resolve_name (char *name)
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_CANONNAME;
#ifdef AI_ADDRCONFIG
hints.ai_flags += AI_ADDRCONFIG;
#endif
err = getaddrinfo (name, "tftp", &hints, &aiptr);
if (err)
@@ -343,7 +340,10 @@ resolve_name (char *name)
memcpy (&peeraddr, ai->ai_addr, ai->ai_addrlen);
connected = 1;
free (hostname);
hostname = xstrdup (ai->ai_canonname);
if (ai->ai_canonname)
hostname = xstrdup (ai->ai_canonname);
else
hostname = xstrdup ("<dummy>");
break;
}

View File

@@ -19,8 +19,12 @@
# Written by Simon Josefsson
# FIXME: Separate tests of IPv4 and IPv6 using `inetd', no testing
# of standalone daemon yet.
# FIXME: Better test coverage!
#
# Implemented: anonymous-only in inetd-mode.
#
# Wanted: * standalone-mode
# * underprivileged mode.
# Address mapping IPv4-to-IPv6 is not uniform an all platforms,
# thus separately using `tcp4' and `tcp6' for streams in `inetd.conf'.
@@ -36,6 +40,14 @@ TARGET=${TARGET:-127.0.0.1}
TARGET6=${TARGET6:-::1}
TARGET46=${TARGET46:-::ffff:127.0.0.1}
# Portability fix for SVR4
PWD="${PWD:-`pwd`}"
# Acting user and target user
#
USER="`id -u -n`"
FTPUSER=${FTPUSER:-ftp}
if [ ! -x $FTP ]; then
echo "No FTP client '$FTP' present. Skipping test" >&2
exit 77
@@ -54,30 +66,35 @@ if [ $VERBOSE ]; then
$INETD --version | head -1
fi
# This script is using '! command' in many tests,
# which is not available in old shells. We fail
# for those old shell releases.
if eval '! false' 2>/dev/null; then
: # This is expected
else
echo 'Presently using the SVR4 Bourne shell.'
echo 'This test needs a recent shell with'
echo 'keyword ! and tilde expansion.'
exit 77
fi
if [ `id -u` != 0 ]; then
echo "ftpd needs to run as root"
echo "ftpd needs to run as root" >&2
exit 77
fi
if ! id -u ftp > /dev/null; then
echo "anonymous ftpd needs a 'ftp' user"
if id -u "$FTPUSER" > /dev/null; then
:
else
echo "anonymous ftpd needs a '$FTPUSER' user" >&2
exit 77
fi
if [ ! -d ~ftp ]; then
echo "the user 'ftp' must have a home directory"
FTPHOME="`eval echo ~"$FTPUSER"`"
if test ! -d "$FTPHOME"; then
save_IFS="$IFS"
IFS=:
set -- `grep "^$FTPUSER:" /etc/passwd` # Existence is known above.
IFS="$save_IFS"
if test ! -d "$6"; then
echo "The user '$FTPUSER' must have a home directory." >&2
exit 77
fi
FTPHOME="$6"
fi
if test -d "$FTPHOME" && test -r "$FTPHOME" && test -x "$FTPHOME"; then
: # We have full access to anonymous' home directory.
else
echo "Insufficient access for $FTPUSER's home directory." >&2
exit 77
fi
@@ -121,23 +138,64 @@ if test -z "$PORT"; then
fi
done
if test "$PORT" = 'none'; then
echo 'Our port allocation failed. Skipping test.'
echo 'Our port allocation failed. Skipping test.' >&2
exit 77
fi
fi
echo "$PORT stream tcp4 nowait root $PWD/$FTPD ftpd -A -l" > $TMPDIR/inetd.conf
echo "$PORT stream tcp6 nowait root $PWD/$FTPD ftpd -A -l" >> $TMPDIR/inetd.conf
echo "machine $TARGET login ftp password foobar" > $TMPDIR/.netrc
echo "machine $TARGET6 login ftp password foobar" >> $TMPDIR/.netrc
echo "machine $TARGET46 login ftp password foobar" >> $TMPDIR/.netrc
cat <<EOT > "$TMPDIR/inetd.conf"
$PORT stream tcp4 nowait $USER $PWD/$FTPD ftpd -A -l
$PORT stream tcp6 nowait $USER $PWD/$FTPD ftpd -A -l
EOT
cat <<EOT > "$TMPDIR/.netrc"
machine $TARGET login $FTPUSER password foobar
machine $TARGET6 login $FTPUSER password foobar
machine $TARGET46 login $FTPUSER password foobar
EOT
chmod 600 $TMPDIR/.netrc
$INETD --pidfile=$TMPDIR/inetd.pid $TMPDIR/inetd.conf
$INETD --pidfile="$TMPDIR/inetd.pid" "$TMPDIR/inetd.conf"
# Wait for inetd to write pid and open socket
sleep 2
# Test evaluation helper
#
# test_report errno output_file hint_msg
#
test_report () {
test -z "${VERBOSE+yes}" || cat "$2"
if [ $1 != 0 ]; then
echo "Running '$FTP' failed with errno $1." >&2
exit 77
fi
# Did we get access?
if grep 'Login failed' "$2" >/dev/null 2>&1; then
echo "Failed login for access using '$3' FTP client." >&2
exit 1
fi
# Standing control connection?
if grep 'FTP server status' "$2" >/dev/null 2>&1; then
:
else
echo "Cannot find server status for '$3' FTP client?" >&2
exit 1
fi
# Was data transfer successful?
if grep '226 Transfer complete.' "$2" >/dev/null 2>&1; then
:
else
echo "Cannot find transfer result for '$3' FTP client?" >&2
exit 1
fi
}
# Test a passive connection: PASV and IPv4.
#
echo "PASV to $TARGET (IPv4) using inetd."
@@ -145,32 +203,9 @@ cat <<STOP |
rstatus
dir
STOP
HOME=$TMPDIR $FTP $TARGET $PORT -4 -v -p -t >$TMPDIR/ftp.stdout
HOME=$TMPDIR $FTP "$TARGET" $PORT -4 -v -p -t >$TMPDIR/ftp.stdout 2>&1
errno=$?
[ -z "$VERBOSE" ] || cat $TMPDIR/ftp.stdout
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output for passive ftp client?
exit 1
fi
# Was data transfer successful?
if ! grep '226 Transfer complete.' $TMPDIR/ftp.stdout; then
echo cannot find transfer result for passive ftp client?
exit 1
fi
test_report $? "$TMPDIR/ftp.stdout" "PASV/$TARGET"
# Test an active connection: PORT and IPv4.
#
@@ -179,32 +214,9 @@ cat <<STOP |
rstatus
dir
STOP
HOME=$TMPDIR $FTP $TARGET $PORT -4 -v -t >$TMPDIR/ftp.stdout
HOME=$TMPDIR $FTP "$TARGET" $PORT -4 -v -t >$TMPDIR/ftp.stdout 2>&1
errno=$?
[ -z "$VERBOSE" ] || cat $TMPDIR/ftp.stdout
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output for active ftp client?
exit 1
fi
# Was data transfer successful?
if ! grep '226 Transfer complete.' $TMPDIR/ftp.stdout; then
echo cannot find transfer result for active ftp client?
exit 1
fi
test_report $? "$TMPDIR/ftp.stdout" "PORT/$TARGET"
# Test a passive connection: EPSV and IPv4.
#
@@ -214,32 +226,9 @@ rstatus
epsv4
dir
STOP
HOME=$TMPDIR $FTP $TARGET $PORT -4 -v -p -t >$TMPDIR/ftp.stdout
HOME=$TMPDIR $FTP "$TARGET" $PORT -4 -v -p -t >$TMPDIR/ftp.stdout 2>&1
errno=$?
[ -z "$VERBOSE" ] || cat $TMPDIR/ftp.stdout
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output for passive ftp client?
exit 1
fi
# Was data transfer successful?
if ! grep '226 Transfer complete.' $TMPDIR/ftp.stdout; then
echo cannot find transfer result for passive ftp client?
exit 1
fi
test_report $? "$TMPDIR/ftp.stdout" "EPSV/$TARGET"
# Test an active connection: EPRT and IPv4.
#
@@ -249,32 +238,9 @@ rstatus
epsv4
dir
STOP
HOME=$TMPDIR $FTP $TARGET $PORT -4 -v -t >$TMPDIR/ftp.stdout
HOME=$TMPDIR $FTP "$TARGET" $PORT -4 -v -t >$TMPDIR/ftp.stdout 2>&1
errno=$?
[ -z "$VERBOSE" ] || cat $TMPDIR/ftp.stdout
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output for active ftp client?
exit 1
fi
# Was data transfer successful?
if ! grep '226 Transfer complete.' $TMPDIR/ftp.stdout; then
echo cannot find transfer result for active ftp client?
exit 1
fi
test_report $? "$TMPDIR/ftp.stdout" "EPRT/$TARGET"
# Test a passive connection: EPSV and IPv6.
#
@@ -283,32 +249,9 @@ cat <<STOP |
rstatus
dir
STOP
HOME=$TMPDIR $FTP $TARGET6 $PORT -6 -v -p -t >$TMPDIR/ftp.stdout
HOME=$TMPDIR $FTP "$TARGET6" $PORT -6 -v -p -t >$TMPDIR/ftp.stdout 2>&1
errno=$?
[ -z "$VERBOSE" ] || cat $TMPDIR/ftp.stdout
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output for passive ftp client?
exit 1
fi
# Was data transfer successful?
if ! grep '226 Transfer complete.' $TMPDIR/ftp.stdout; then
echo cannot find transfer result for passive ftp client?
exit 1
fi
test_report $? "$TMPDIR/ftp.stdout" "EPSV/$TARGET6"
# Test an active connection: EPRT and IPv6.
#
@@ -317,32 +260,9 @@ cat <<STOP |
rstatus
dir
STOP
HOME=$TMPDIR $FTP $TARGET6 $PORT -6 -v -t >$TMPDIR/ftp.stdout
HOME=$TMPDIR $FTP "$TARGET6" $PORT -6 -v -t >$TMPDIR/ftp.stdout 2>&1
errno=$?
[ -z "$VERBOSE" ] || cat $TMPDIR/ftp.stdout
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output for active ftp client?
exit 1
fi
# Was data transfer successful?
if ! grep '226 Transfer complete.' $TMPDIR/ftp.stdout; then
echo cannot find transfer result for active ftp client?
exit 1
fi
test_report $? "$TMPDIR/ftp.stdout" "EPRT/$TARGET6"
# Availability of IPv4-mapped IPv6 addresses.
#
@@ -358,16 +278,20 @@ have_address_mapping=false
# OpenSolaris is known to allow address mapping
test `uname -s` = 'SunOS' && have_address_mapping=true
if ! $have_address_mapping; then
if $have_address_mapping; then
:
else
# Do we have sysctl(1) available?
if ! which sysctl >/dev/null 2>&1; then
echo "Warning: Not testing IPv4-mapped addresses."
else
if which sysctl >/dev/null 2>&1; then
have_sysctl=true
else
echo "Warning: Not testing IPv4-mapped addresses." >&2
fi
fi
if ! $have_address_mapping && $have_sysctl; then
if $have_address_mapping; then
:
elif $have_sysctl; then
# Extract the present setting of
#
# net.ipv6.bindv6only (Linux)
@@ -381,7 +305,7 @@ if ! $have_address_mapping && $have_sysctl; then
# This is the good value. Keep it.
have_address_mapping=true
else
echo "Warning: Address mapping IPv4-to-Ipv6 is disabled."
echo "Warning: Address mapping IPv4-to-Ipv6 is disabled." >&2
# Set a non-zero value for later testing.
value_v6only=2
fi
@@ -401,32 +325,9 @@ if $have_address_mapping && test -n "$TARGET46" ; then
rstatus
dir
STOP
HOME=$TMPDIR $FTP $TARGET46 $PORT -6 -v -p -t >$TMPDIR/ftp.stdout
HOME=$TMPDIR $FTP "$TARGET46" $PORT -6 -v -p -t >$TMPDIR/ftp.stdout 2>&1
errno=$?
[ -z "$VERBOSE" ] || cat $TMPDIR/ftp.stdout
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output for passive ftp client?
exit 1
fi
# Was data transfer successful?
if ! grep '226 Transfer complete.' $TMPDIR/ftp.stdout; then
echo cannot find transfer result for passive ftp client?
exit 1
fi
test_report $? "$TMPDIR/ftp.stdout" "EPSV/$TARGET46"
# Test an active connection: EPRT and IPvIPv6.
#
@@ -435,32 +336,9 @@ if $have_address_mapping && test -n "$TARGET46" ; then
rstatus
dir
STOP
HOME=$TMPDIR $FTP $TARGET46 $PORT -6 -v -t >$TMPDIR/ftp.stdout
HOME=$TMPDIR $FTP "$TARGET46" $PORT -6 -v -t >$TMPDIR/ftp.stdout 2>&1
errno=$?
[ -z "$VERBOSE" ] || cat $TMPDIR/ftp.stdout
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
if [ $errno != 0 ]; then
echo running ftp failed? errno $errno
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output for active ftp client?
exit 1
fi
# Was data transfer successful?
if ! grep '226 Transfer complete.' $TMPDIR/ftp.stdout; then
echo cannot find transfer result for active ftp client?
exit 1
fi
test_report $? "$TMPDIR/ftp.stdout" "EPRT/$TARGET46"
else
# The IPv4-as-IPv6 tests were not performed.
echo 'Skipping two tests of IPv4 mapped as IPv6.'

View File

@@ -45,6 +45,9 @@ HERE
exit 0
fi
# Portability fix for SVR4
PWD="${PWD:-`pwd`}"
# Execution control. Initialise early!
#
do_cleandir=false

View File

@@ -19,12 +19,13 @@
# Run `inetd' with `tftpd' and try to fetch a file from there using `tftp'.
# FIXME: Presently tailored for IPv4.
if [ "$VERBOSE" ]; then
set -x
fi
# Portability fix for SVR4
PWD="${PWD:-`pwd`}"
TFTP="${TFTP:-../src/tftp$EXEEXT}"
TFTPD="${TFTPD:-$PWD/../src/tftpd$EXEEXT}"
INETD="${INETD:-../src/inetd$EXEEXT}"
@@ -65,13 +66,13 @@ posttesting () {
trap posttesting EXIT HUP INT QUIT TERM
# Use only "127.0.0.1" as default address list.
# Use only "127.0.0.1 ::1" as default address list.
# Other configured addresses might be set under
# strict filter policies, thus might block.
#
# Allow a setting "ADDRESSES=sense" to compute the
# available addresses and then to test them all.
ADDRESSES="${ADDRESSES:-127.0.0.1}"
ADDRESSES="${ADDRESSES:-127.0.0.1 ::1}"
if [ "$ADDRESSES" = "sense" ]; then
ADDRESSES="`$IFCONFIG | sed -e "/$AF /!d" \
@@ -81,28 +82,29 @@ fi
# Check that netstat works before proceeding.
netstat -na > /dev/null
if [ ! $? -eq 0 ]; then
echo "netstat: command failed to execute successfully"
echo "netstat: command failed to execute successfully" >&2
exit 77
fi
# Work around the peculiar output of netstat(1m,solaris).
#
# locate_port family proto port
# locate_port proto port
#
locate_port () {
if [ "`uname -s`" = "SunOS" ]; then
netstat -na -f$1 -P$2 |
grep "\.$3[^0-9]" >/dev/null 2>&1
netstat -na -finet -finet6 -P$1 |
grep "\.$2[^0-9]" >/dev/null 2>&1
else
netstat -na |
grep "^$2\(4\|6\|46\)\{0,1\}.*[^0-9]$3[^0-9]" >/dev/null 2>&1
grep "^$1\(4\|6\|46\)\{0,1\}.*[^0-9]$2[^0-9]" >/dev/null 2>&1
fi
}
if [ "$VERBOSE" ]; then
"$TFTP" --version
"$TFTPD" --version
"$INETD" --version
"$TFTP" --version | head -1
"$TFTPD" --version | head -1
"$INETD" --version | head -1
"$IFCONFIG_SIMPLE" --version | head -1
fi
# Find an available port number. There will be some
@@ -112,27 +114,29 @@ fi
if test -z "$PORT"; then
for PORT in 7777 7779 7783 7791 7807 7839 none; do
test $PORT = none && break
if locate_port $AF $PROTO $PORT; then
if locate_port $PROTO $PORT; then
continue
else
break
fi
done
if test "$PORT" = 'none'; then
echo 'Our port allocation failed. Skipping test.'
echo 'Our port allocation failed. Skipping test.' >&2
exit 77
fi
fi
# Create `inetd.conf'. Note: We want $TFTPD to be an absolute file
# name because `inetd' chdirs to `/' in daemon mode; ditto for
# $INETD_CONF.
# $INETD_CONF. Thus the dependency on file locations will be
# identical in daemon-mode and in debug-mode.
cat > "$INETD_CONF" <<EOF
$PORT dgram ${PROTO}4 wait $USER $TFTPD tftpd -l $TMPDIR/tftp-test
$PORT dgram ${PROTO}6 wait $USER $TFTPD tftpd -l $TMPDIR/tftp-test
EOF
# Launch `inetd', assuming it's reachable at all $ADDRESSES.
$INETD -d -p"$INETD_PID" "$INETD_CONF" &
$INETD ${VERBOSE+-d} -p"$INETD_PID" "$INETD_CONF" &
sleep 1
inetd_pid="`cat $INETD_PID`"
@@ -142,7 +146,7 @@ test -z "$VERBOSE" || echo "Launched Inetd as process $inetd_pid." >&2
sleep 1
# Did `inetd' really succeed in establishing a listener?
locate_port $AF $PROTO $PORT
locate_port $PROTO $PORT
if test $? -ne 0; then
# No it did not.
ps "$inetd_pid" >/dev/null 2>&1 && kill "$inetd_pid" 2>/dev/null
@@ -191,7 +195,7 @@ for addr in $ADDRESSES; do
for name in $FILELIST; do
EFFORTS=`expr $EFFORTS + 1`
rm -f $name
echo "get $name" | "$TFTP" $addr $PORT
echo "get $name" | "$TFTP" ${VERBOSE+-v} "$addr" $PORT
cmp "$TMPDIR/tftp-test/$name" "$name" 2>/dev/null
result=$?