1package ProFTPD::Tests::Config::RLimitOpenFiles; 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 rlimitopenfiles_max => { 19 order => ++$order, 20 test_class => [qw(forking)], 21 }, 22 23 rlimitopenfiles_session_max => { 24 order => ++$order, 25 test_class => [qw(forking)], 26 }, 27 28 rlimitopenfiles_session_min => { 29 order => ++$order, 30 test_class => [qw(forking)], 31 }, 32 33 rlimitopenfiles_daemon_max => { 34 order => ++$order, 35 test_class => [qw(bug forking)], 36 }, 37 38 rlimitopenfiles_daemon_min => { 39 order => ++$order, 40 test_class => [qw(bug forking)], 41 }, 42 43}; 44 45sub new { 46 return shift()->SUPER::new(@_); 47} 48 49sub list_tests { 50 return testsuite_get_runnable_tests($TESTS); 51} 52 53sub rlimitopenfiles_max { 54 my $self = shift; 55 my $tmpdir = $self->{tmpdir}; 56 57 my $config_file = "$tmpdir/config.conf"; 58 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 59 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 60 61 my $log_file = test_get_logfile(); 62 63 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 64 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 65 66 my $user = 'proftpd'; 67 my $passwd = 'test'; 68 my $group = 'ftpd'; 69 my $home_dir = File::Spec->rel2abs($tmpdir); 70 my $uid = 500; 71 my $gid = 500; 72 73 # Make sure that, if we're running as root, that the home directory has 74 # permissions/privs set for the account we create 75 if ($< == 0) { 76 unless (chmod(0755, $home_dir)) { 77 die("Can't set perms on $home_dir to 0755: $!"); 78 } 79 80 unless (chown($uid, $gid, $home_dir)) { 81 die("Can't set owner of $home_dir to $uid/$gid: $!"); 82 } 83 } 84 85 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 86 '/bin/bash'); 87 auth_group_write($auth_group_file, $group, $gid, $user); 88 89 my $config = { 90 PidFile => $pid_file, 91 ScoreboardFile => $scoreboard_file, 92 SystemLog => $log_file, 93 94 AuthUserFile => $auth_user_file, 95 AuthGroupFile => $auth_group_file, 96 97 RLimitOpenFiles => 'max', 98 99 IfModules => { 100 'mod_delay.c' => { 101 DelayEngine => 'off', 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 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 124 $client->login($user, $passwd); 125 $client->quit(); 126 }; 127 128 if ($@) { 129 $ex = $@; 130 } 131 132 $wfh->print("done\n"); 133 $wfh->flush(); 134 135 } else { 136 eval { server_wait($config_file, $rfh) }; 137 if ($@) { 138 warn($@); 139 exit 1; 140 } 141 142 exit 0; 143 } 144 145 # Stop server 146 server_stop($pid_file); 147 148 $self->assert_child_ok($pid); 149 150 if ($ex) { 151 test_append_logfile($log_file, $ex); 152 unlink($log_file); 153 154 die($ex); 155 } 156 157 unlink($log_file); 158} 159 160sub rlimitopenfiles_session_max { 161 my $self = shift; 162 my $tmpdir = $self->{tmpdir}; 163 164 my $config_file = "$tmpdir/config.conf"; 165 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 166 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 167 168 my $log_file = test_get_logfile(); 169 170 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 171 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 172 173 my $user = 'proftpd'; 174 my $passwd = 'test'; 175 my $group = 'ftpd'; 176 my $home_dir = File::Spec->rel2abs($tmpdir); 177 my $uid = 500; 178 my $gid = 500; 179 180 # Make sure that, if we're running as root, that the home directory has 181 # permissions/privs set for the account we create 182 if ($< == 0) { 183 unless (chmod(0755, $home_dir)) { 184 die("Can't set perms on $home_dir to 0755: $!"); 185 } 186 187 unless (chown($uid, $gid, $home_dir)) { 188 die("Can't set owner of $home_dir to $uid/$gid: $!"); 189 } 190 } 191 192 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 193 '/bin/bash'); 194 auth_group_write($auth_group_file, $group, $gid, $user); 195 196 my $config = { 197 PidFile => $pid_file, 198 ScoreboardFile => $scoreboard_file, 199 SystemLog => $log_file, 200 201 AuthUserFile => $auth_user_file, 202 AuthGroupFile => $auth_group_file, 203 204 RLimitOpenFiles => 'session max', 205 206 IfModules => { 207 'mod_delay.c' => { 208 DelayEngine => 'off', 209 }, 210 }, 211 }; 212 213 my ($port, $config_user, $config_group) = config_write($config_file, $config); 214 215 # Open pipes, for use between the parent and child processes. Specifically, 216 # the child will indicate when it's done with its test by writing a message 217 # to the parent. 218 my ($rfh, $wfh); 219 unless (pipe($rfh, $wfh)) { 220 die("Can't open pipe: $!"); 221 } 222 223 my $ex; 224 225 # Fork child 226 $self->handle_sigchld(); 227 defined(my $pid = fork()) or die("Can't fork: $!"); 228 if ($pid) { 229 eval { 230 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 231 $client->login($user, $passwd); 232 $client->quit(); 233 }; 234 235 if ($@) { 236 $ex = $@; 237 } 238 239 $wfh->print("done\n"); 240 $wfh->flush(); 241 242 } else { 243 eval { server_wait($config_file, $rfh) }; 244 if ($@) { 245 warn($@); 246 exit 1; 247 } 248 249 exit 0; 250 } 251 252 # Stop server 253 server_stop($pid_file); 254 255 $self->assert_child_ok($pid); 256 257 if ($ex) { 258 test_append_logfile($log_file, $ex); 259 unlink($log_file); 260 261 die($ex); 262 } 263 264 unlink($log_file); 265} 266 267sub rlimitopenfiles_session_min { 268 my $self = shift; 269 my $tmpdir = $self->{tmpdir}; 270 271 my $config_file = "$tmpdir/config.conf"; 272 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 273 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 274 275 my $log_file = test_get_logfile(); 276 277 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 278 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 279 280 my $user = 'proftpd'; 281 my $passwd = 'test'; 282 my $group = 'ftpd'; 283 my $home_dir = File::Spec->rel2abs($tmpdir); 284 my $uid = 500; 285 my $gid = 500; 286 287 # Make sure that, if we're running as root, that the home directory has 288 # permissions/privs set for the account we create 289 if ($< == 0) { 290 unless (chmod(0755, $home_dir)) { 291 die("Can't set perms on $home_dir to 0755: $!"); 292 } 293 294 unless (chown($uid, $gid, $home_dir)) { 295 die("Can't set owner of $home_dir to $uid/$gid: $!"); 296 } 297 } 298 299 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 300 '/bin/bash'); 301 auth_group_write($auth_group_file, $group, $gid, $user); 302 303 my $config = { 304 PidFile => $pid_file, 305 ScoreboardFile => $scoreboard_file, 306 SystemLog => $log_file, 307 308 AuthUserFile => $auth_user_file, 309 AuthGroupFile => $auth_group_file, 310 311 RLimitOpenFiles => 'session 6', 312 313 IfModules => { 314 'mod_delay.c' => { 315 DelayEngine => 'off', 316 }, 317 }, 318 }; 319 320 my ($port, $config_user, $config_group) = config_write($config_file, $config); 321 322 # Open pipes, for use between the parent and child processes. Specifically, 323 # the child will indicate when it's done with its test by writing a message 324 # to the parent. 325 my ($rfh, $wfh); 326 unless (pipe($rfh, $wfh)) { 327 die("Can't open pipe: $!"); 328 } 329 330 my $ex; 331 332 # Fork child 333 $self->handle_sigchld(); 334 defined(my $pid = fork()) or die("Can't fork: $!"); 335 if ($pid) { 336 eval { 337 # We allotted enough fds to allow client to connect, but NOT to login 338 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 339 eval { $client->login($user, $passwd) }; 340 unless ($@) { 341 die("Login succeeded unexpectedly"); 342 } 343 344 $client->quit(); 345 }; 346 347 if ($@) { 348 $ex = $@; 349 } 350 351 $wfh->print("done\n"); 352 $wfh->flush(); 353 354 } else { 355 eval { server_wait($config_file, $rfh) }; 356 if ($@) { 357 warn($@); 358 exit 1; 359 } 360 361 exit 0; 362 } 363 364 # Stop server 365 server_stop($pid_file); 366 367 $self->assert_child_ok($pid); 368 369 if ($ex) { 370 test_append_logfile($log_file, $ex); 371 unlink($log_file); 372 373 die($ex); 374 } 375 376 unlink($log_file); 377} 378 379sub rlimitopenfiles_daemon_max { 380 my $self = shift; 381 my $tmpdir = $self->{tmpdir}; 382 383 my $config_file = "$tmpdir/config.conf"; 384 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 385 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 386 387 my $log_file = test_get_logfile(); 388 389 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 390 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 391 392 my $user = 'proftpd'; 393 my $passwd = 'test'; 394 my $group = 'ftpd'; 395 my $home_dir = File::Spec->rel2abs($tmpdir); 396 my $uid = 500; 397 my $gid = 500; 398 399 # Make sure that, if we're running as root, that the home directory has 400 # permissions/privs set for the account we create 401 if ($< == 0) { 402 unless (chmod(0755, $home_dir)) { 403 die("Can't set perms on $home_dir to 0755: $!"); 404 } 405 406 unless (chown($uid, $gid, $home_dir)) { 407 die("Can't set owner of $home_dir to $uid/$gid: $!"); 408 } 409 } 410 411 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 412 '/bin/bash'); 413 auth_group_write($auth_group_file, $group, $gid, $user); 414 415 my $config = { 416 PidFile => $pid_file, 417 ScoreboardFile => $scoreboard_file, 418 SystemLog => $log_file, 419 420 AuthUserFile => $auth_user_file, 421 AuthGroupFile => $auth_group_file, 422 423 RLimitOpenFiles => 'daemon max', 424 425 IfModules => { 426 'mod_delay.c' => { 427 DelayEngine => 'off', 428 }, 429 }, 430 }; 431 432 my ($port, $config_user, $config_group) = config_write($config_file, $config); 433 434 # Open pipes, for use between the parent and child processes. Specifically, 435 # the child will indicate when it's done with its test by writing a message 436 # to the parent. 437 my ($rfh, $wfh); 438 unless (pipe($rfh, $wfh)) { 439 die("Can't open pipe: $!"); 440 } 441 442 my $ex; 443 444 # Fork child 445 $self->handle_sigchld(); 446 defined(my $pid = fork()) or die("Can't fork: $!"); 447 if ($pid) { 448 eval { 449 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 450 $client->login($user, $passwd); 451 $client->quit(); 452 }; 453 454 if ($@) { 455 $ex = $@; 456 } 457 458 $wfh->print("done\n"); 459 $wfh->flush(); 460 461 } else { 462 eval { server_wait($config_file, $rfh) }; 463 if ($@) { 464 warn($@); 465 exit 1; 466 } 467 468 exit 0; 469 } 470 471 # Stop server 472 server_stop($pid_file); 473 474 $self->assert_child_ok($pid); 475 476 if ($ex) { 477 test_append_logfile($log_file, $ex); 478 unlink($log_file); 479 480 die($ex); 481 } 482 483 unlink($log_file); 484} 485 486sub rlimitopenfiles_daemon_min { 487 my $self = shift; 488 my $tmpdir = $self->{tmpdir}; 489 490 my $config_file = "$tmpdir/config.conf"; 491 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 492 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 493 494 my $log_file = test_get_logfile(); 495 496 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 497 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 498 499 my $user = 'proftpd'; 500 my $passwd = 'test'; 501 my $group = 'ftpd'; 502 my $home_dir = File::Spec->rel2abs($tmpdir); 503 my $uid = 500; 504 my $gid = 500; 505 506 # Make sure that, if we're running as root, that the home directory has 507 # permissions/privs set for the account we create 508 if ($< == 0) { 509 unless (chmod(0755, $home_dir)) { 510 die("Can't set perms on $home_dir to 0755: $!"); 511 } 512 513 unless (chown($uid, $gid, $home_dir)) { 514 die("Can't set owner of $home_dir to $uid/$gid: $!"); 515 } 516 } 517 518 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 519 '/bin/bash'); 520 auth_group_write($auth_group_file, $group, $gid, $user); 521 522 my $config = { 523 PidFile => $pid_file, 524 ScoreboardFile => $scoreboard_file, 525 SystemLog => $log_file, 526 527 AuthUserFile => $auth_user_file, 528 AuthGroupFile => $auth_group_file, 529 530 RLimitOpenFiles => 'daemon 3', 531 532 IfModules => { 533 'mod_delay.c' => { 534 DelayEngine => 'off', 535 }, 536 }, 537 }; 538 539 my ($port, $config_user, $config_group) = config_write($config_file, $config); 540 541 # Open pipes, for use between the parent and child processes. Specifically, 542 # the child will indicate when it's done with its test by writing a message 543 # to the parent. 544 my ($rfh, $wfh); 545 unless (pipe($rfh, $wfh)) { 546 die("Can't open pipe: $!"); 547 } 548 549 my $ex; 550 551 # Fork child 552 $self->handle_sigchld(); 553 defined(my $pid = fork()) or die("Can't fork: $!"); 554 if ($pid) { 555 eval { 556 # We allowed just enough fds for the server to start up, but not 557 # much else. 558 eval { ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1) }; 559 unless ($@) { 560 die("Connecting to server succeeded unexpectedly"); 561 } 562 }; 563 564 if ($@) { 565 $ex = $@; 566 } 567 568 $wfh->print("done\n"); 569 $wfh->flush(); 570 571 } else { 572 eval { server_wait($config_file, $rfh) }; 573 if ($@) { 574 warn($@); 575 exit 1; 576 } 577 578 exit 0; 579 } 580 581 # Stop server 582 server_stop($pid_file); 583 584 $self->assert_child_ok($pid); 585 586 if ($ex) { 587 test_append_logfile($log_file, $ex); 588 unlink($log_file); 589 590 die($ex); 591 } 592 593# unlink($log_file); 594} 595 5961; 597