1package ProFTPD::Tests::Config::MaxTransfersPerHost; 2 3use lib qw(t/lib); 4use base qw(ProFTPD::TestSuite::Child); 5use strict; 6 7use File::Spec; 8use IO::Handle; 9 10use ProFTPD::TestSuite::FTP; 11use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite); 12 13$| = 1; 14 15my $order = 0; 16 17my $TESTS = { 18 maxtransfersperhost_retr => { 19 order => ++$order, 20 test_class => [qw(forking)], 21 }, 22 23 maxtransfersperhost_retr_custom_message => { 24 order => ++$order, 25 test_class => [qw(forking)], 26 }, 27 28}; 29 30sub new { 31 return shift()->SUPER::new(@_); 32} 33 34sub list_tests { 35 return testsuite_get_runnable_tests($TESTS); 36} 37 38sub maxtransfersperhost_retr { 39 my $self = shift; 40 my $tmpdir = $self->{tmpdir}; 41 my $setup = test_setup($tmpdir, 'config'); 42 43 my $test_file = File::Spec->rel2abs($setup->{config_file}); 44 my $max_transfers = 1; 45 46 my $config = { 47 PidFile => $setup->{pid_file}, 48 ScoreboardFile => $setup->{scoreboard_file}, 49 SystemLog => $setup->{log_file}, 50 51 AuthUserFile => $setup->{auth_user_file}, 52 AuthGroupFile => $setup->{auth_group_file}, 53 MaxTransfersPerHost => "RETR $max_transfers", 54 55 IfModules => { 56 'mod_delay.c' => { 57 DelayEngine => 'off', 58 }, 59 }, 60 }; 61 62 my ($port, $config_user, $config_group) = config_write($setup->{config_file}, 63 $config); 64 65 # Open pipes, for use between the parent and child processes. Specifically, 66 # the child will indicate when it's done with its test by writing a message 67 # to the parent. 68 my ($rfh, $wfh); 69 unless (pipe($rfh, $wfh)) { 70 die("Can't open pipe: $!"); 71 } 72 73 my $ex; 74 75 # Fork child 76 $self->handle_sigchld(); 77 defined(my $pid = fork()) or die("Can't fork: $!"); 78 if ($pid) { 79 eval { 80 # First client should be able to connect and log in... 81 my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 82 $client1->login($setup->{user}, $setup->{passwd}); 83 my $conn1 = $client1->retr_raw($test_file); 84 unless ($conn1) { 85 die("RETR failed: " . $client1->response_code() . " " . 86 $client1->response_msg()); 87 } 88 89 my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 90 $client2->login($setup->{user}, $setup->{passwd}); 91 my $conn2 = $client2->retr_raw($test_file); 92 if ($conn2) { 93 die("RETR succeeded unexpectedly"); 94 } 95 96 my $resp_code = $client2->response_code(); 97 my $resp_msg = $client2->response_msg(); 98 99 my $expected; 100 101 $expected = 451; 102 $self->assert($expected == $resp_code, 103 test_msg("Expected response code $expected, got $resp_code")); 104 105 $expected = "Sorry, the maximum number of data transfers ($max_transfers) from your host are currently being used."; 106 $self->assert($expected eq $resp_msg, 107 test_msg("Expected response message '$expected', got '$resp_msg'")); 108 109 $client1->quit(); 110 $client2->quit(); 111 }; 112 113 if ($@) { 114 $ex = $@; 115 } 116 117 $wfh->print("done\n"); 118 $wfh->flush(); 119 120 } else { 121 eval { server_wait($setup->{config_file}, $rfh) }; 122 if ($@) { 123 warn($@); 124 exit 1; 125 } 126 127 exit 0; 128 } 129 130 # Stop server 131 server_stop($setup->{pid_file}); 132 133 $self->assert_child_ok($pid); 134 test_cleanup($setup->{log_file}, $ex); 135} 136 137sub maxtransfersperhost_retr_custom_message { 138 my $self = shift; 139 my $tmpdir = $self->{tmpdir}; 140 my $setup = test_setup($tmpdir, 'config'); 141 142 my $test_file = File::Spec->rel2abs($setup->{config_file}); 143 my $max_transfers = 1; 144 145 my $config = { 146 PidFile => $setup->{pid_file}, 147 ScoreboardFile => $setup->{scoreboard_file}, 148 SystemLog => $setup->{log_file}, 149 150 AuthUserFile => $setup->{auth_user_file}, 151 AuthGroupFile => $setup->{auth_group_file}, 152 MaxTransfersPerHost => "RETR $max_transfers \"Too many transfers from your host\"", 153 154 IfModules => { 155 'mod_delay.c' => { 156 DelayEngine => 'off', 157 }, 158 }, 159 }; 160 161 my ($port, $config_user, $config_group) = config_write($setup->{config_file}, 162 $config); 163 164 # Open pipes, for use between the parent and child processes. Specifically, 165 # the child will indicate when it's done with its test by writing a message 166 # to the parent. 167 my ($rfh, $wfh); 168 unless (pipe($rfh, $wfh)) { 169 die("Can't open pipe: $!"); 170 } 171 172 my $ex; 173 174 # Fork child 175 $self->handle_sigchld(); 176 defined(my $pid = fork()) or die("Can't fork: $!"); 177 if ($pid) { 178 eval { 179 # First client should be able to connect and log in... 180 my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 181 $client1->login($setup->{user}, $setup->{passwd}); 182 my $conn1 = $client1->retr_raw($test_file); 183 unless ($conn1) { 184 die("RETR failed: " . $client1->response_code() . " " . 185 $client1->response_msg()); 186 } 187 188 my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 189 $client2->login($setup->{user}, $setup->{passwd}); 190 my $conn2 = $client2->retr_raw($test_file); 191 if ($conn2) { 192 die("RETR succeeded unexpectedly"); 193 } 194 195 my $resp_code = $client2->response_code(); 196 my $resp_msg = $client2->response_msg(); 197 198 my $expected; 199 200 $expected = 451; 201 $self->assert($expected == $resp_code, 202 test_msg("Expected response code $expected, got $resp_code")); 203 204 $expected = 'Too many transfers from your host'; 205 $self->assert($expected eq $resp_msg, 206 test_msg("Expected response message '$expected', got '$resp_msg'")); 207 208 $client1->quit(); 209 $client2->quit(); 210 }; 211 212 if ($@) { 213 $ex = $@; 214 } 215 216 $wfh->print("done\n"); 217 $wfh->flush(); 218 219 } else { 220 eval { server_wait($setup->{config_file}, $rfh) }; 221 if ($@) { 222 warn($@); 223 exit 1; 224 } 225 226 exit 0; 227 } 228 229 # Stop server 230 server_stop($setup->{pid_file}); 231 232 $self->assert_child_ok($pid); 233 test_cleanup($setup->{log_file}, $ex); 234} 235 2361; 237