From: TJ S. <cas...@us...> - 2009-04-30 18:54:36
|
Update of /cvsroot/proftp/proftpd/tests/t/lib/ProFTPD/Tests/Commands In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv22536/t/lib/ProFTPD/Tests/Commands Modified Files: PORT.pm Log Message: A proftpd user in the forums mentioned encountering the "Cannot assign requested address" error when attempting active data transfers. Add a unit test which demonstrates how this error can occur (usually because of badly behaved FTP clients which do not cleanly close the data connection once done with it). Index: PORT.pm =================================================================== RCS file: /cvsroot/proftp/proftpd/tests/t/lib/ProFTPD/Tests/Commands/PORT.pm,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- PORT.pm 20 Nov 2008 00:35:07 -0000 1.4 +++ PORT.pm 30 Apr 2009 18:54:19 -0000 1.5 @@ -46,6 +46,11 @@ test_class => [qw(forking)], }, + port_eaddrnotavail => { + order => ++$order, + test_class => [qw(forking)], + }, + }; sub new { @@ -77,7 +82,7 @@ } undef $self; -}; +} sub port_ok { my $self = shift; @@ -86,7 +91,8 @@ my $config_file = "$tmpdir/cmds.conf"; my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid"); my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard"); - my $log_file = File::Spec->rel2abs('cmds.log'); + + my $log_file = File::Spec->rel2abs('tests.log'); my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd"); my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group"); @@ -158,7 +164,6 @@ test_msg("Expected $expected, got $resp_code")); $expected = "PORT command successful"; - chomp($resp_msg); $self->assert($expected eq $resp_msg, test_msg("Expected '$expected', got '$resp_msg'")); }; @@ -199,7 +204,8 @@ my $config_file = "$tmpdir/cmds.conf"; my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid"); my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard"); - my $log_file = File::Spec->rel2abs('cmds.log'); + + my $log_file = File::Spec->rel2abs('tests.log'); my $config = { PidFile => $pid_file, @@ -249,7 +255,6 @@ test_msg("Expected $expected, got $resp_code")); $expected = "Please login with USER and PASS"; - chomp($resp_msg); $self->assert($expected eq $resp_msg, test_msg("Expected '$expected', got '$resp_msg'")); }; @@ -290,7 +295,8 @@ my $config_file = "$tmpdir/cmds.conf"; my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid"); my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard"); - my $log_file = File::Spec->rel2abs('cmds.log'); + + my $log_file = File::Spec->rel2abs('tests.log'); my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd"); my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group"); @@ -370,7 +376,6 @@ test_msg("Expected $expected, got $resp_code")); $expected = "Illegal PORT command"; - chomp($resp_msg); $self->assert($expected eq $resp_msg, test_msg("Expected '$expected', got '$resp_msg'")); }; @@ -411,7 +416,8 @@ my $config_file = "$tmpdir/cmds.conf"; my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid"); my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard"); - my $log_file = File::Spec->rel2abs('cmds.log'); + + my $log_file = File::Spec->rel2abs('tests.log'); my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd"); my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group"); @@ -490,7 +496,6 @@ test_msg("Expected $expected, got $resp_code")); $expected = "Illegal PORT command"; - chomp($resp_msg); $self->assert($expected eq $resp_msg, test_msg("Expected '$expected', got '$resp_msg'")); }; @@ -531,7 +536,8 @@ my $config_file = "$tmpdir/cmds.conf"; my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid"); my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard"); - my $log_file = File::Spec->rel2abs('cmds.log'); + + my $log_file = File::Spec->rel2abs('tests.log'); my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd"); my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group"); @@ -612,7 +618,6 @@ test_msg("Expected $expected, got $resp_code")); $expected = "Illegal PORT command"; - chomp($resp_msg); $self->assert($expected eq $resp_msg, test_msg("Expected '$expected', got '$resp_msg'")); }; @@ -653,7 +658,8 @@ my $config_file = "$tmpdir/cmds.conf"; my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid"); my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard"); - my $log_file = File::Spec->rel2abs('cmds.log'); + + my $log_file = File::Spec->rel2abs('tests.log'); my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd"); my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group"); @@ -734,7 +740,6 @@ test_msg("Expected $expected, got $resp_code")); $expected = "Illegal PORT command"; - chomp($resp_msg); $self->assert($expected eq $resp_msg, test_msg("Expected '$expected', got '$resp_msg'")); }; @@ -768,4 +773,163 @@ unlink($log_file); } +sub port_eaddrnotavail { + my $self = shift; + my $tmpdir = $self->{tmpdir}; + + my $config_file = "$tmpdir/cmds.conf"; + my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid"); + my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard"); + + my $log_file = File::Spec->rel2abs('tests.log'); + + my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd"); + my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group"); + + my $user = 'proftpd'; + my $passwd = 'test'; + my $home_dir = File::Spec->rel2abs($tmpdir); + my $uid = 500; + my $gid = 500; + + # Make sure that, if we're running as root, that the home directory has + # permissions/privs set for the account we create + if ($< == 0) { + unless (chmod(0755, $home_dir)) { + die("Can't set perms on $home_dir to 0755: $!"); + } + + unless (chown($uid, $gid, $home_dir)) { + die("Can't set owner of $home_dir to $uid/$gid: $!"); + } + } + + auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, + '/bin/bash'); + auth_group_write($auth_group_file, 'ftpd', $gid, $user); + + my $config = { + PidFile => $pid_file, + ScoreboardFile => $scoreboard_file, + SystemLog => $log_file, + + AuthUserFile => $auth_user_file, + AuthGroupFile => $auth_group_file, + + IfModules => { + 'mod_delay.c' => { + DelayEngine => 'off', + }, + }, + }; + + my ($port, $config_user, $config_group) = config_write($config_file, $config); + + # Open pipes, for use between the parent and child processes. Specifically, + # the child will indicate when it's done with its test by writing a message + # to the parent. + my ($rfh, $wfh); + unless (pipe($rfh, $wfh)) { + die("Can't open pipe: $!"); + } + + my $ex; + + # Fork child + $self->handle_sigchld(); + defined(my $pid = fork()) or die("Can't fork: $!"); + if ($pid) { + eval { + my $arg = '127,0,0,1,4,1'; + + my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); + $client1->login($user, $passwd); + + my ($resp_code, $resp_msg); + ($resp_code, $resp_msg) = $client1->port($arg); + + my $expected; + + $expected = 200; + $self->assert($expected == $resp_code, + test_msg("Expected $expected, got $resp_code")); + + $expected = "PORT command successful"; + $self->assert($expected eq $resp_msg, + test_msg("Expected '$expected', got '$resp_msg'")); + + my $conn1 = $client1->list_raw(); + unless ($conn1) { + die("Failed to LIST: " . $client1->response_code() . " " . + $client1->response_msg()); + } + + my $buf1; + $conn1->read($buf1, 32768); + + # Explicitly do NOT close the connection here. We keep it open, so + # as to trigger an error when the second client tries to use the + # exact same PORT argument for its transfer. + + my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); + $client2->login($user, $passwd); + + ($resp_code, $resp_msg) = $client2->port($arg); + + my $expected; + + $expected = 200; + $self->assert($expected == $resp_code, + test_msg("Expected $expected, got $resp_code")); + + $expected = "PORT command successful"; + $self->assert($expected eq $resp_msg, + test_msg("Expected '$expected', got '$resp_msg'")); + + eval { $client2->list() }; + unless ($@) { + die("LIST succeeded unexpectedly"); + } + + $resp_code = $client2->response_code(); + $resp_msg = $client2->response_msg(); + + $expected = 425; + $self->assert($expected == $resp_code, + test_msg("Expected $expected, got $resp_code")); + + $expected = 'Unable to build data connection: (Cannot assign requested address|Address already in use)'; + $self->assert(qr/$expected/, $resp_msg, + test_msg("Expected '$expected', got '$resp_msg'")); + }; + + if ($@) { + $ex = $@; + } + + $wfh->print("done\n"); + $wfh->flush(); + + } else { + eval { server_wait($config_file, $rfh) }; + if ($@) { + warn($@); + exit 1; + } + + exit 0; + } + + # Stop server + server_stop($pid_file); + + $self->assert_child_ok($pid); + + if ($ex) { + die($ex); + } + + unlink($log_file); +} + 1; |