1package ProFTPD::Tests::Config::RLimitCPU; 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 rlimitcpu_max => { 19 order => ++$order, 20 test_class => [qw(forking)], 21 }, 22 23 rlimitcpu_session_max => { 24 order => ++$order, 25 test_class => [qw(forking)], 26 }, 27 28 rlimitcpu_session_min => { 29 order => ++$order, 30 test_class => [qw(forking)], 31 }, 32 33 rlimitcpu_daemon_max => { 34 order => ++$order, 35 test_class => [qw(forking)], 36 }, 37 38 rlimitcpu_daemon_min => { 39 order => ++$order, 40 test_class => [qw(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 rlimitcpu_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 RLimitCPU => '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 rlimitcpu_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 RLimitCPU => '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 rlimitcpu_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 RLimitCPU => 'session 0', 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 eval { ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1) }; 338 unless ($@) { 339 die("Connecting to server succeeded unexpectedly"); 340 } 341 }; 342 343 if ($@) { 344 $ex = $@; 345 } 346 347 $wfh->print("done\n"); 348 $wfh->flush(); 349 350 } else { 351 eval { server_wait($config_file, $rfh) }; 352 if ($@) { 353 warn($@); 354 exit 1; 355 } 356 357 exit 0; 358 } 359 360 if ($ex) { 361 test_append_logfile($log_file, $ex); 362 unlink($log_file); 363 364 die($ex); 365 } 366 367 unlink($log_file); 368} 369 370sub rlimitcpu_daemon_max { 371 my $self = shift; 372 my $tmpdir = $self->{tmpdir}; 373 374 my $config_file = "$tmpdir/config.conf"; 375 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 376 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 377 378 my $log_file = test_get_logfile(); 379 380 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 381 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 382 383 my $user = 'proftpd'; 384 my $passwd = 'test'; 385 my $group = 'ftpd'; 386 my $home_dir = File::Spec->rel2abs($tmpdir); 387 my $uid = 500; 388 my $gid = 500; 389 390 # Make sure that, if we're running as root, that the home directory has 391 # permissions/privs set for the account we create 392 if ($< == 0) { 393 unless (chmod(0755, $home_dir)) { 394 die("Can't set perms on $home_dir to 0755: $!"); 395 } 396 397 unless (chown($uid, $gid, $home_dir)) { 398 die("Can't set owner of $home_dir to $uid/$gid: $!"); 399 } 400 } 401 402 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 403 '/bin/bash'); 404 auth_group_write($auth_group_file, $group, $gid, $user); 405 406 my $config = { 407 PidFile => $pid_file, 408 ScoreboardFile => $scoreboard_file, 409 SystemLog => $log_file, 410 411 AuthUserFile => $auth_user_file, 412 AuthGroupFile => $auth_group_file, 413 414 RLimitCPU => 'daemon max', 415 416 IfModules => { 417 'mod_delay.c' => { 418 DelayEngine => 'off', 419 }, 420 }, 421 }; 422 423 my ($port, $config_user, $config_group) = config_write($config_file, $config); 424 425 # Open pipes, for use between the parent and child processes. Specifically, 426 # the child will indicate when it's done with its test by writing a message 427 # to the parent. 428 my ($rfh, $wfh); 429 unless (pipe($rfh, $wfh)) { 430 die("Can't open pipe: $!"); 431 } 432 433 my $ex; 434 435 # Fork child 436 $self->handle_sigchld(); 437 defined(my $pid = fork()) or die("Can't fork: $!"); 438 if ($pid) { 439 eval { 440 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 441 $client->login($user, $passwd); 442 $client->quit(); 443 }; 444 445 if ($@) { 446 $ex = $@; 447 } 448 449 $wfh->print("done\n"); 450 $wfh->flush(); 451 452 } else { 453 eval { server_wait($config_file, $rfh) }; 454 if ($@) { 455 warn($@); 456 exit 1; 457 } 458 459 exit 0; 460 } 461 462 # Stop server 463 server_stop($pid_file); 464 465 $self->assert_child_ok($pid); 466 467 if ($ex) { 468 test_append_logfile($log_file, $ex); 469 unlink($log_file); 470 471 die($ex); 472 } 473 474 unlink($log_file); 475} 476 477sub rlimitcpu_daemon_min { 478 my $self = shift; 479 my $tmpdir = $self->{tmpdir}; 480 481 my $config_file = "$tmpdir/config.conf"; 482 my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid"); 483 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard"); 484 485 my $log_file = test_get_logfile(); 486 487 my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd"); 488 my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group"); 489 490 my $user = 'proftpd'; 491 my $passwd = 'test'; 492 my $group = 'ftpd'; 493 my $home_dir = File::Spec->rel2abs($tmpdir); 494 my $uid = 500; 495 my $gid = 500; 496 497 # Make sure that, if we're running as root, that the home directory has 498 # permissions/privs set for the account we create 499 if ($< == 0) { 500 unless (chmod(0755, $home_dir)) { 501 die("Can't set perms on $home_dir to 0755: $!"); 502 } 503 504 unless (chown($uid, $gid, $home_dir)) { 505 die("Can't set owner of $home_dir to $uid/$gid: $!"); 506 } 507 } 508 509 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 510 '/bin/bash'); 511 auth_group_write($auth_group_file, $group, $gid, $user); 512 513 my $config = { 514 PidFile => $pid_file, 515 ScoreboardFile => $scoreboard_file, 516 SystemLog => $log_file, 517 518 AuthUserFile => $auth_user_file, 519 AuthGroupFile => $auth_group_file, 520 521 RLimitCPU => 'daemon 0', 522 523 IfModules => { 524 'mod_delay.c' => { 525 DelayEngine => 'off', 526 }, 527 }, 528 }; 529 530 my ($port, $config_user, $config_group) = config_write($config_file, $config); 531 532 my $ex; 533 534 eval { server_start($config_file, $pid_file) }; 535 unless ($@) { 536 # Stop server 537 server_stop($pid_file); 538 539 $ex = "Server started up successfully unexpectedly"; 540 } 541 542 if ($ex) { 543 test_append_logfile($log_file, $ex); 544 unlink($log_file); 545 546 die($ex); 547 } 548 549 unlink($log_file); 550} 551 5521; 553