1package ProFTPD::Tests::Config::Limit::LOGIN; 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 login_limit_ip_glob_range_bug3484 => { 19 order => ++$order, 20 test_class => [qw(bug forking inprogress)], 21 }, 22 23 login_limit_allowgroup_backslash => { 24 order => ++$order, 25 test_class => [qw(bug forking)], 26 }, 27 28 login_limit_multiple_sections => { 29 order => ++$order, 30 test_class => [qw(bug forking)], 31 }, 32 33}; 34 35sub new { 36 return shift()->SUPER::new(@_); 37} 38 39sub list_tests { 40 return testsuite_get_runnable_tests($TESTS); 41} 42 43sub login_limit_ip_glob_range_bug3484 { 44 my $self = shift; 45 my $tmpdir = $self->{tmpdir}; 46 47 my $config_file = "$tmpdir/limit.conf"; 48 my $pid_file = File::Spec->rel2abs("$tmpdir/limit.pid"); 49 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/limit.scoreboard"); 50 51 my $log_file = test_get_logfile(); 52 53 my $auth_user_file = File::Spec->rel2abs("$tmpdir/limit.passwd"); 54 my $auth_group_file = File::Spec->rel2abs("$tmpdir/limit.group"); 55 56 my $user = 'proftpd'; 57 my $passwd = 'test'; 58 my $group ='ftpd'; 59 my $home_dir = File::Spec->rel2abs($tmpdir); 60 my $uid = 500; 61 my $gid = 500; 62 63 # Make sure that, if we're running as root, that the home directory has 64 # permissions/privs set for the account we create 65 if ($< == 0) { 66 unless (chmod(0755, $home_dir)) { 67 die("Can't set perms on $home_dir to 0755: $!"); 68 } 69 70 unless (chown($uid, $gid, $home_dir)) { 71 die("Can't set owner of $home_dir to $uid/$gid: $!"); 72 } 73 } 74 75 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 76 '/bin/bash'); 77 auth_group_write($auth_group_file, $group, $gid, $user); 78 79 # See http://forums.proftpd.org/smf/index.php/topic,4774.0.html 80 81 my $config = { 82 PidFile => $pid_file, 83 ScoreboardFile => $scoreboard_file, 84 SystemLog => $log_file, 85 TraceLog => $log_file, 86 Trace => 'netacl:20 dns:20', 87 88 AuthUserFile => $auth_user_file, 89 AuthGroupFile => $auth_group_file, 90 UseIPv6 => 'off', 91 92 IfModules => { 93 'mod_delay.c' => { 94 DelayEngine => 'off', 95 }, 96 }, 97 98 Limit => { 99 LOGIN => { 100 Deny => '127.0.0.[0-9]', 101 }, 102 }, 103 104 }; 105 106 my ($port, $config_user, $config_group) = config_write($config_file, $config); 107 108 # Open pipes, for use between the parent and child processes. Specifically, 109 # the child will indicate when it's done with its test by writing a message 110 # to the parent. 111 my ($rfh, $wfh); 112 unless (pipe($rfh, $wfh)) { 113 die("Can't open pipe: $!"); 114 } 115 116 my $ex; 117 118 # Fork child 119 $self->handle_sigchld(); 120 defined(my $pid = fork()) or die("Can't fork: $!"); 121 if ($pid) { 122 eval { 123 my $client; 124 125 eval { $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 126 undef, 0) }; 127 unless ($@) { 128 die("Connect succeeded unexpectedly"); 129 } 130 131 my $conn_ex = ProFTPD::TestSuite::FTP::get_connect_exception(); 132 133 my $expected = 'Connection refused'; 134 $self->assert(qr/$expected/, $conn_ex, 135 test_msg("Expected '$expected', got '$conn_ex'")); 136 }; 137 138 if ($@) { 139 $ex = $@; 140 } 141 142 $wfh->print("done\n"); 143 $wfh->flush(); 144 145 } else { 146 eval { server_wait($config_file, $rfh) }; 147 if ($@) { 148 warn($@); 149 exit 1; 150 } 151 152 exit 0; 153 } 154 155 # Stop server 156 server_stop($pid_file); 157 158 $self->assert_child_ok($pid); 159 160 if ($ex) { 161 test_append_logfile($log_file, $ex); 162 unlink($log_file); 163 164 die($ex); 165 } 166 167 unlink($log_file); 168} 169 170sub login_limit_allowgroup_backslash { 171 my $self = shift; 172 my $tmpdir = $self->{tmpdir}; 173 174 my $config_file = "$tmpdir/limit.conf"; 175 my $pid_file = File::Spec->rel2abs("$tmpdir/limit.pid"); 176 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/limit.scoreboard"); 177 178 my $log_file = test_get_logfile(); 179 180 my $auth_user_file = File::Spec->rel2abs("$tmpdir/limit.passwd"); 181 my $auth_group_file = File::Spec->rel2abs("$tmpdir/limit.group"); 182 183 # See: 184 # https://forums.proftpd.org/smf/index.php/topic,11304.0.html 185 186 my $user = 'proftpd'; 187 my $passwd = 'test'; 188 my $group = 'ftpd\group'; 189 my $home_dir = File::Spec->rel2abs($tmpdir); 190 my $uid = 500; 191 my $gid = 500; 192 193 # Make sure that, if we're running as root, that the home directory has 194 # permissions/privs set for the account we create 195 if ($< == 0) { 196 unless (chmod(0755, $home_dir)) { 197 die("Can't set perms on $home_dir to 0755: $!"); 198 } 199 200 unless (chown($uid, $gid, $home_dir)) { 201 die("Can't set owner of $home_dir to $uid/$gid: $!"); 202 } 203 } 204 205 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 206 '/bin/bash'); 207 auth_group_write($auth_group_file, $group, $gid, $user); 208 209 # See http://forums.proftpd.org/smf/index.php/topic,4774.0.html 210 211 my $config = { 212 PidFile => $pid_file, 213 ScoreboardFile => $scoreboard_file, 214 SystemLog => $log_file, 215 TraceLog => $log_file, 216 Trace => 'netacl:20 dns:20', 217 218 AuthUserFile => $auth_user_file, 219 AuthGroupFile => $auth_group_file, 220 UseIPv6 => 'off', 221 222 IfModules => { 223 'mod_delay.c' => { 224 DelayEngine => 'off', 225 }, 226 }, 227 228 Limit => { 229 LOGIN => { 230 AllowGroup => $group, 231 DenyAll => '', 232 }, 233 }, 234 235 }; 236 237 my ($port, $config_user, $config_group) = config_write($config_file, $config); 238 239 # Open pipes, for use between the parent and child processes. Specifically, 240 # the child will indicate when it's done with its test by writing a message 241 # to the parent. 242 my ($rfh, $wfh); 243 unless (pipe($rfh, $wfh)) { 244 die("Can't open pipe: $!"); 245 } 246 247 my $ex; 248 249 # Fork child 250 $self->handle_sigchld(); 251 defined(my $pid = fork()) or die("Can't fork: $!"); 252 if ($pid) { 253 eval { 254 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 255 $client->login($user, $passwd); 256 $client->quit(); 257 }; 258 259 if ($@) { 260 $ex = $@; 261 } 262 263 $wfh->print("done\n"); 264 $wfh->flush(); 265 266 } else { 267 eval { server_wait($config_file, $rfh) }; 268 if ($@) { 269 warn($@); 270 exit 1; 271 } 272 273 exit 0; 274 } 275 276 # Stop server 277 server_stop($pid_file); 278 279 $self->assert_child_ok($pid); 280 281 if ($ex) { 282 test_append_logfile($log_file, $ex); 283 unlink($log_file); 284 285 die($ex); 286 } 287 288 unlink($log_file); 289} 290 291sub login_limit_multiple_sections { 292 my $self = shift; 293 my $tmpdir = $self->{tmpdir}; 294 295 my $config_file = "$tmpdir/limit.conf"; 296 my $pid_file = File::Spec->rel2abs("$tmpdir/limit.pid"); 297 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/limit.scoreboard"); 298 299 my $log_file = test_get_logfile(); 300 301 my $auth_user_file = File::Spec->rel2abs("$tmpdir/limit.passwd"); 302 my $auth_group_file = File::Spec->rel2abs("$tmpdir/limit.group"); 303 304 my $user = 'proftpd'; 305 my $passwd = 'test'; 306 my $group ='ftpd'; 307 my $home_dir = File::Spec->rel2abs($tmpdir); 308 my $uid = 500; 309 my $gid = 500; 310 311 # Make sure that, if we're running as root, that the home directory has 312 # permissions/privs set for the account we create 313 if ($< == 0) { 314 unless (chmod(0755, $home_dir)) { 315 die("Can't set perms on $home_dir to 0755: $!"); 316 } 317 318 unless (chown($uid, $gid, $home_dir)) { 319 die("Can't set owner of $home_dir to $uid/$gid: $!"); 320 } 321 } 322 323 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 324 '/bin/bash'); 325 auth_group_write($auth_group_file, $group, $gid, $user); 326 327 # See http://forums.proftpd.org/smf/index.php/topic,4774.0.html 328 329 my $config = { 330 PidFile => $pid_file, 331 ScoreboardFile => $scoreboard_file, 332 SystemLog => $log_file, 333 TraceLog => $log_file, 334 Trace => 'netacl:20 dns:20', 335 336 AuthUserFile => $auth_user_file, 337 AuthGroupFile => $auth_group_file, 338 UseIPv6 => 'off', 339 340 IfModules => { 341 'mod_delay.c' => { 342 DelayEngine => 'off', 343 }, 344 }, 345 }; 346 347 my ($port, $config_user, $config_group) = config_write($config_file, $config); 348 349 if (open(my $fh, ">> $config_file")) { 350 # When multiple <Limit LOGIN> sections are present, which one is used: 351 # first, or last? 352 print $fh <<EOC; 353<Limit LOGIN> 354 Order allow,deny 355 Allow 127.0.0.1 356 DenyAll 357</Limit> 358 359<Limit LOGIN> 360 Order deny,allow 361 Deny 127.0.0.1 362</Limit> 363 364EOC 365 unless (close($fh)) { 366 die("Can't write $config_file: $!"); 367 } 368 } else { 369 die("Can't open $config_file: $!"); 370 } 371 372 # Open pipes, for use between the parent and child processes. Specifically, 373 # the child will indicate when it's done with its test by writing a message 374 # to the parent. 375 my ($rfh, $wfh); 376 unless (pipe($rfh, $wfh)) { 377 die("Can't open pipe: $!"); 378 } 379 380 my $ex; 381 382 # Fork child 383 $self->handle_sigchld(); 384 defined(my $pid = fork()) or die("Can't fork: $!"); 385 if ($pid) { 386 eval { 387 my $client; 388 389 eval { $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 390 undef, 0) }; 391 unless ($@) { 392 die("Connect succeeded unexpectedly"); 393 } 394 395 my $conn_ex = ProFTPD::TestSuite::FTP::get_connect_exception(); 396 397 # Looks like the last <Limit LOGIN> section wins. 398 my $expected = 'Connection refused'; 399 $self->assert(qr/$expected/, $conn_ex, 400 test_msg("Expected '$expected', got '$conn_ex'")); 401 }; 402 403 if ($@) { 404 $ex = $@; 405 } 406 407 $wfh->print("done\n"); 408 $wfh->flush(); 409 410 } else { 411 eval { server_wait($config_file, $rfh) }; 412 if ($@) { 413 warn($@); 414 exit 1; 415 } 416 417 exit 0; 418 } 419 420 # Stop server 421 server_stop($pid_file); 422 423 $self->assert_child_ok($pid); 424 425 if ($ex) { 426 test_append_logfile($log_file, $ex); 427 unlink($log_file); 428 429 die($ex); 430 } 431 432 unlink($log_file); 433} 434 4351; 436