diff --git a/ChangeLog b/ChangeLog index b854c55b..2b80687a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2012-01-31 Mats Erik Andersson + + * 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 `', 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 * 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 diff --git a/src/tftp.c b/src/tftp.c index 4332a167..d191b030 100644 --- a/src/tftp.c +++ b/src/tftp.c @@ -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 (""); break; } diff --git a/tests/ftp-localhost.sh b/tests/ftp-localhost.sh index 1c7ef07e..194a411b 100755 --- a/tests/ftp-localhost.sh +++ b/tests/ftp-localhost.sh @@ -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 < "$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 < "$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 <$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 <$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 <$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 <$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.' diff --git a/tests/syslogd.sh b/tests/syslogd.sh index 6438654f..ebd584d4 100755 --- a/tests/syslogd.sh +++ b/tests/syslogd.sh @@ -45,6 +45,9 @@ HERE exit 0 fi +# Portability fix for SVR4 +PWD="${PWD:-`pwd`}" + # Execution control. Initialise early! # do_cleandir=false diff --git a/tests/tftp.sh b/tests/tftp.sh index 24c43bf2..af6e8e1f 100755 --- a/tests/tftp.sh +++ b/tests/tftp.sh @@ -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" <&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=$?