ftpd: Regression with active connections.

In using an active connection, the port was not cleared properly,
leading to a missed port allocation in bind().  A minor portability
issue lead to change of hints for getaddrinfo() in resolving `host_port'.
This commit is contained in:
Mats Erik Andersson
2012-01-04 18:33:06 +01:00
parent a6e53e7914
commit dd43de5f41
4 changed files with 69 additions and 5 deletions

View File

@@ -1,3 +1,13 @@
2012-01-04 Mats Erik Andersson <gnu@gisladisker.se>
Regression: Erase port for active data transmission.
* ftpd/ftpcmd.y (host_port): Use AI_NUMERICHOST and AI_NUMERICSERV
in `HINTS.ai_flags'. Do not use AI_ADDRCONFIG.
* ftpd/ftpd.c (getdatasock): Erase port number stored in DATA_SOURCE.
* tests/ftp-localhost.sh: Detect transfered data and duplicate tests
also for an active connection, not only a passive attempt.
2012-01-03 Alfred M. Szmidt <ams@gnu.org>
* bootstrap.conf (gnulib_modules): Removed git-merge-changelog.

View File

@@ -620,9 +620,8 @@ host_port
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
#ifdef AI_ADDRCONFIG
hints.ai_flags = AI_ADDRCONFIG;
#endif
hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
err = getaddrinfo (a, p, &hints, &res);
if (err)
reply (550, "Address failure: %s,%s", a, p);

View File

@@ -1037,10 +1037,23 @@ getdatasock (const char *mode)
goto bad;
}
/* anchor socket to avoid multi-homing problems */
/* Anchor socket to avoid multi-homing problems. */
memcpy (&data_source, &ctrl_addr, sizeof (data_source));
data_source_len = ctrl_addrlen;
/* Erase port number, suggesting bind() to allocate a new port. */
switch (data_source.ss_family)
{
case AF_INET6:
((struct sockaddr_in6 *) &data_source)->sin6_port = 0;
break;
case AF_INET:
((struct sockaddr_in *) &data_source)->sin_port = 0;
break;
default:
break; /* Do nothing; should not happen! */
}
for (tries = 1;; tries++)
{
if (bind (s, (struct sockaddr *) &data_source, data_source_len) >= 0)

View File

@@ -74,6 +74,8 @@ $INETD --pidfile=$TMPDIR/inetd.pid $TMPDIR/inetd.conf
# Wait for inetd to write pid and open socket
sleep 2
# Test a passive connection.
#
cat <<STOP |
rstatus
dir
@@ -93,8 +95,48 @@ if [ $errno != 0 ]; then
exit 77
fi
# Standing control connection?
if ! grep 'FTP server status' $TMPDIR/ftp.stdout; then
echo cannot find expected output from ftp client?
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 an active connection.
#
cat <<STOP |
rstatus
dir
STOP
HOME=$TMPDIR $FTP $TARGET 4711 -4 -v -t >$TMPDIR/ftp.stdout
errno=$?
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