1package ProFTPD::Tests::Modules::mod_auth_file; 2 3use lib qw(t/lib); 4use base qw(ProFTPD::TestSuite::Child); 5use strict; 6 7use Cwd; 8use File::Path qw(mkpath); 9use File::Spec; 10use IO::Handle; 11 12use ProFTPD::TestSuite::FTP; 13use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite); 14 15$| = 1; 16 17my $order = 0; 18 19my $TESTS = { 20 auth_user_file_id_range_ok => { 21 order => ++$order, 22 test_class => [qw(forking)], 23 }, 24 25 auth_user_file_id_range_failed => { 26 order => ++$order, 27 test_class => [qw(forking)], 28 }, 29 30 auth_user_file_home_filter_ok => { 31 order => ++$order, 32 test_class => [qw(forking)], 33 }, 34 35 auth_user_file_home_filter_failed => { 36 order => ++$order, 37 test_class => [qw(forking)], 38 }, 39 40 auth_user_file_name_filter_ok => { 41 order => ++$order, 42 test_class => [qw(forking)], 43 }, 44 45 auth_user_file_name_filter_failed => { 46 order => ++$order, 47 test_class => [qw(forking)], 48 }, 49 50 auth_group_file_id_range_ok => { 51 order => ++$order, 52 test_class => [qw(forking)], 53 }, 54 55 auth_group_file_id_range_failed => { 56 order => ++$order, 57 test_class => [qw(forking)], 58 }, 59 60 auth_group_file_name_filter_ok => { 61 order => ++$order, 62 test_class => [qw(forking)], 63 }, 64 65 auth_group_file_name_filter_failed => { 66 order => ++$order, 67 test_class => [qw(forking)], 68 }, 69 70 auth_user_file_at_symbol_ok => { 71 order => ++$order, 72 test_class => [qw(forking)], 73 }, 74 75 auth_user_file_world_readable_bug3892 => { 76 order => ++$order, 77 test_class => [qw(bug forking)], 78 }, 79 80 auth_user_file_world_writable_bug3892 => { 81 order => ++$order, 82 test_class => [qw(bug forking)], 83 }, 84 85 auth_user_file_world_readable_insecure_perms_opt => { 86 order => ++$order, 87 test_class => [qw(bug forking)], 88 }, 89 90 auth_group_file_world_readable_bug3892 => { 91 order => ++$order, 92 test_class => [qw(bug forking)], 93 }, 94 95 auth_group_file_world_writable_bug3892 => { 96 order => ++$order, 97 test_class => [qw(bug forking)], 98 }, 99 100 auth_user_file_world_writable_parent_dir_bug3892 => { 101 order => ++$order, 102 test_class => [qw(bug forking)], 103 }, 104 105 auth_user_file_symlink_world_writable_parent_dir_bug3892 => { 106 order => ++$order, 107 test_class => [qw(bug forking)], 108 }, 109 110 auth_user_file_bad_syntax_bug3985 => { 111 order => ++$order, 112 test_class => [qw(bug forking)], 113 }, 114 115 auth_group_file_bad_syntax_bug3985 => { 116 order => ++$order, 117 test_class => [qw(bug forking)], 118 }, 119 120 auth_file_symlink_segfault_bug4145 => { 121 order => ++$order, 122 test_class => [qw(bug forking)], 123 }, 124 125}; 126 127sub new { 128 return shift()->SUPER::new(@_); 129} 130 131sub list_tests { 132 return testsuite_get_runnable_tests($TESTS); 133} 134 135sub auth_user_file_id_range_ok { 136 my $self = shift; 137 my $tmpdir = $self->{tmpdir}; 138 139 my $config_file = "$tmpdir/authfile.conf"; 140 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 141 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 142 143 my $log_file = test_get_logfile(); 144 145 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 146 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 147 148 my $user = 'proftpd'; 149 my $passwd = 'test'; 150 my $group = 'ftpd'; 151 my $home_dir = File::Spec->rel2abs($tmpdir); 152 my $uid = 500; 153 my $gid = 500; 154 155 # Make sure that, if we're running as root, that the home directory has 156 # permissions/privs set for the account we create 157 if ($< == 0) { 158 unless (chmod(0755, $home_dir)) { 159 die("Can't set perms on $home_dir to 0755: $!"); 160 } 161 162 unless (chown($uid, $gid, $home_dir)) { 163 die("Can't set owner of $home_dir to $uid/$gid: $!"); 164 } 165 } 166 167 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 168 '/bin/bash'); 169 auth_group_write($auth_group_file, $group, $gid, $user); 170 171 my $config = { 172 PidFile => $pid_file, 173 ScoreboardFile => $scoreboard_file, 174 SystemLog => $log_file, 175 176 AuthUserFile => "$auth_user_file id 100-500", 177 AuthGroupFile => $auth_group_file, 178 179 IfModules => { 180 'mod_delay.c' => { 181 DelayEngine => 'off', 182 }, 183 }, 184 }; 185 186 my ($port, $config_user, $config_group) = config_write($config_file, $config); 187 188 # Open pipes, for use between the parent and child processes. Specifically, 189 # the child will indicate when it's done with its test by writing a message 190 # to the parent. 191 my ($rfh, $wfh); 192 unless (pipe($rfh, $wfh)) { 193 die("Can't open pipe: $!"); 194 } 195 196 my $ex; 197 198 # Fork child 199 $self->handle_sigchld(); 200 defined(my $pid = fork()) or die("Can't fork: $!"); 201 if ($pid) { 202 eval { 203 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 204 $client->login($user, $passwd); 205 $client->quit(); 206 }; 207 208 if ($@) { 209 $ex = $@; 210 } 211 212 $wfh->print("done\n"); 213 $wfh->flush(); 214 215 } else { 216 eval { server_wait($config_file, $rfh) }; 217 if ($@) { 218 warn($@); 219 exit 1; 220 } 221 222 exit 0; 223 } 224 225 # Stop server 226 server_stop($pid_file); 227 228 $self->assert_child_ok($pid); 229 230 if ($ex) { 231 test_append_logfile($log_file, $ex); 232 unlink($log_file); 233 234 die($ex); 235 } 236 237 unlink($log_file); 238} 239 240sub auth_user_file_id_range_failed { 241 my $self = shift; 242 my $tmpdir = $self->{tmpdir}; 243 244 my $config_file = "$tmpdir/authfile.conf"; 245 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 246 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 247 248 my $log_file = test_get_logfile(); 249 250 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 251 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 252 253 my $user = 'proftpd'; 254 my $passwd = 'test'; 255 my $group = 'ftpd'; 256 my $home_dir = File::Spec->rel2abs($tmpdir); 257 my $uid = 1000; 258 my $gid = 1000; 259 260 # Make sure that, if we're running as root, that the home directory has 261 # permissions/privs set for the account we create 262 if ($< == 0) { 263 unless (chmod(0755, $home_dir)) { 264 die("Can't set perms on $home_dir to 0755: $!"); 265 } 266 267 unless (chown($uid, $gid, $home_dir)) { 268 die("Can't set owner of $home_dir to $uid/$gid: $!"); 269 } 270 } 271 272 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 273 '/bin/bash'); 274 auth_group_write($auth_group_file, $group, $gid, $user); 275 276 my $config = { 277 PidFile => $pid_file, 278 ScoreboardFile => $scoreboard_file, 279 SystemLog => $log_file, 280 281 AuthUserFile => "$auth_user_file id 100-500", 282 AuthGroupFile => $auth_group_file, 283 284 IfModules => { 285 'mod_delay.c' => { 286 DelayEngine => 'off', 287 }, 288 }, 289 }; 290 291 my ($port, $config_user, $config_group) = config_write($config_file, $config); 292 293 # Open pipes, for use between the parent and child processes. Specifically, 294 # the child will indicate when it's done with its test by writing a message 295 # to the parent. 296 my ($rfh, $wfh); 297 unless (pipe($rfh, $wfh)) { 298 die("Can't open pipe: $!"); 299 } 300 301 my $ex; 302 303 # Fork child 304 $self->handle_sigchld(); 305 defined(my $pid = fork()) or die("Can't fork: $!"); 306 if ($pid) { 307 eval { 308 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 309 eval { $client->login($user, $passwd) }; 310 unless ($@) { 311 die("Login succeeded unexpectedly"); 312 } 313 314 $client->quit(); 315 }; 316 317 if ($@) { 318 $ex = $@; 319 } 320 321 $wfh->print("done\n"); 322 $wfh->flush(); 323 324 } else { 325 eval { server_wait($config_file, $rfh) }; 326 if ($@) { 327 warn($@); 328 exit 1; 329 } 330 331 exit 0; 332 } 333 334 # Stop server 335 server_stop($pid_file); 336 337 $self->assert_child_ok($pid); 338 339 if ($ex) { 340 test_append_logfile($log_file, $ex); 341 unlink($log_file); 342 343 die($ex); 344 } 345 346 unlink($log_file); 347} 348 349sub auth_user_file_home_filter_ok { 350 my $self = shift; 351 my $tmpdir = $self->{tmpdir}; 352 353 my $config_file = "$tmpdir/authfile.conf"; 354 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 355 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 356 357 my $log_file = test_get_logfile(); 358 359 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 360 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 361 362 my $user = 'proftpd'; 363 my $passwd = 'test'; 364 my $group = 'ftpd'; 365 my $home_dir = File::Spec->rel2abs("$tmpdir/$user"); 366 mkpath($home_dir); 367 my $uid = 500; 368 my $gid = 500; 369 370 # Make sure that, if we're running as root, that the home directory has 371 # permissions/privs set for the account we create 372 if ($< == 0) { 373 unless (chmod(0755, $home_dir)) { 374 die("Can't set perms on $home_dir to 0755: $!"); 375 } 376 377 unless (chown($uid, $gid, $home_dir)) { 378 die("Can't set owner of $home_dir to $uid/$gid: $!"); 379 } 380 } 381 382 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 383 '/bin/bash'); 384 auth_group_write($auth_group_file, $group, $gid, $user); 385 386 my $config = { 387 PidFile => $pid_file, 388 ScoreboardFile => $scoreboard_file, 389 SystemLog => $log_file, 390 391 AuthUserFile => "$auth_user_file home $user\$", 392 AuthGroupFile => $auth_group_file, 393 394 IfModules => { 395 'mod_delay.c' => { 396 DelayEngine => 'off', 397 }, 398 }, 399 }; 400 401 my ($port, $config_user, $config_group) = config_write($config_file, $config); 402 403 # Open pipes, for use between the parent and child processes. Specifically, 404 # the child will indicate when it's done with its test by writing a message 405 # to the parent. 406 my ($rfh, $wfh); 407 unless (pipe($rfh, $wfh)) { 408 die("Can't open pipe: $!"); 409 } 410 411 my $ex; 412 413 # Fork child 414 $self->handle_sigchld(); 415 defined(my $pid = fork()) or die("Can't fork: $!"); 416 if ($pid) { 417 eval { 418 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 419 $client->login($user, $passwd); 420 $client->quit(); 421 }; 422 423 if ($@) { 424 $ex = $@; 425 } 426 427 $wfh->print("done\n"); 428 $wfh->flush(); 429 430 } else { 431 eval { server_wait($config_file, $rfh) }; 432 if ($@) { 433 warn($@); 434 exit 1; 435 } 436 437 exit 0; 438 } 439 440 # Stop server 441 server_stop($pid_file); 442 443 $self->assert_child_ok($pid); 444 445 if ($ex) { 446 test_append_logfile($log_file, $ex); 447 unlink($log_file); 448 449 die($ex); 450 } 451 452 unlink($log_file); 453} 454 455sub auth_user_file_home_filter_failed { 456 my $self = shift; 457 my $tmpdir = $self->{tmpdir}; 458 459 my $config_file = "$tmpdir/authfile.conf"; 460 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 461 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 462 463 my $log_file = test_get_logfile(); 464 465 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 466 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 467 468 my $user = 'proftpd'; 469 my $passwd = 'test'; 470 my $group = 'ftpd'; 471 my $home_dir = File::Spec->rel2abs($tmpdir); 472 my $uid = 500; 473 my $gid = 500; 474 475 # Make sure that, if we're running as root, that the home directory has 476 # permissions/privs set for the account we create 477 if ($< == 0) { 478 unless (chmod(0755, $home_dir)) { 479 die("Can't set perms on $home_dir to 0755: $!"); 480 } 481 482 unless (chown($uid, $gid, $home_dir)) { 483 die("Can't set owner of $home_dir to $uid/$gid: $!"); 484 } 485 } 486 487 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 488 '/bin/bash'); 489 auth_group_write($auth_group_file, $group, $gid, $user); 490 491 my $config = { 492 PidFile => $pid_file, 493 ScoreboardFile => $scoreboard_file, 494 SystemLog => $log_file, 495 496 AuthUserFile => "$auth_user_file home ^3133tH\@x0R\$", 497 AuthGroupFile => $auth_group_file, 498 499 IfModules => { 500 'mod_delay.c' => { 501 DelayEngine => 'off', 502 }, 503 }, 504 }; 505 506 my ($port, $config_user, $config_group) = config_write($config_file, $config); 507 508 # Open pipes, for use between the parent and child processes. Specifically, 509 # the child will indicate when it's done with its test by writing a message 510 # to the parent. 511 my ($rfh, $wfh); 512 unless (pipe($rfh, $wfh)) { 513 die("Can't open pipe: $!"); 514 } 515 516 my $ex; 517 518 # Fork child 519 $self->handle_sigchld(); 520 defined(my $pid = fork()) or die("Can't fork: $!"); 521 if ($pid) { 522 eval { 523 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 524 eval { $client->login($user, $passwd) }; 525 unless ($@) { 526 die("Login succeeded unexpectedly"); 527 } 528 529 $client->quit(); 530 }; 531 532 if ($@) { 533 $ex = $@; 534 } 535 536 $wfh->print("done\n"); 537 $wfh->flush(); 538 539 } else { 540 eval { server_wait($config_file, $rfh) }; 541 if ($@) { 542 warn($@); 543 exit 1; 544 } 545 546 exit 0; 547 } 548 549 # Stop server 550 server_stop($pid_file); 551 552 $self->assert_child_ok($pid); 553 554 if ($ex) { 555 test_append_logfile($log_file, $ex); 556 unlink($log_file); 557 558 die($ex); 559 } 560 561 unlink($log_file); 562} 563 564sub auth_user_file_name_filter_ok { 565 my $self = shift; 566 my $tmpdir = $self->{tmpdir}; 567 568 my $config_file = "$tmpdir/authfile.conf"; 569 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 570 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 571 572 my $log_file = test_get_logfile(); 573 574 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 575 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 576 577 my $user = 'proftpd'; 578 my $passwd = 'test'; 579 my $group = 'ftpd'; 580 my $home_dir = File::Spec->rel2abs($tmpdir); 581 my $uid = 500; 582 my $gid = 500; 583 584 # Make sure that, if we're running as root, that the home directory has 585 # permissions/privs set for the account we create 586 if ($< == 0) { 587 unless (chmod(0755, $home_dir)) { 588 die("Can't set perms on $home_dir to 0755: $!"); 589 } 590 591 unless (chown($uid, $gid, $home_dir)) { 592 die("Can't set owner of $home_dir to $uid/$gid: $!"); 593 } 594 } 595 596 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 597 '/bin/bash'); 598 auth_group_write($auth_group_file, $group, $gid, $user); 599 600 my $config = { 601 PidFile => $pid_file, 602 ScoreboardFile => $scoreboard_file, 603 SystemLog => $log_file, 604 605 AuthUserFile => "$auth_user_file name ^$user\$", 606 AuthGroupFile => $auth_group_file, 607 608 IfModules => { 609 'mod_delay.c' => { 610 DelayEngine => 'off', 611 }, 612 }, 613 }; 614 615 my ($port, $config_user, $config_group) = config_write($config_file, $config); 616 617 # Open pipes, for use between the parent and child processes. Specifically, 618 # the child will indicate when it's done with its test by writing a message 619 # to the parent. 620 my ($rfh, $wfh); 621 unless (pipe($rfh, $wfh)) { 622 die("Can't open pipe: $!"); 623 } 624 625 my $ex; 626 627 # Fork child 628 $self->handle_sigchld(); 629 defined(my $pid = fork()) or die("Can't fork: $!"); 630 if ($pid) { 631 eval { 632 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 633 $client->login($user, $passwd); 634 $client->quit(); 635 }; 636 637 if ($@) { 638 $ex = $@; 639 } 640 641 $wfh->print("done\n"); 642 $wfh->flush(); 643 644 } else { 645 eval { server_wait($config_file, $rfh) }; 646 if ($@) { 647 warn($@); 648 exit 1; 649 } 650 651 exit 0; 652 } 653 654 # Stop server 655 server_stop($pid_file); 656 657 $self->assert_child_ok($pid); 658 659 if ($ex) { 660 test_append_logfile($log_file, $ex); 661 unlink($log_file); 662 663 die($ex); 664 } 665 666 unlink($log_file); 667} 668 669sub auth_user_file_name_filter_failed { 670 my $self = shift; 671 my $tmpdir = $self->{tmpdir}; 672 673 my $config_file = "$tmpdir/authfile.conf"; 674 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 675 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 676 677 my $log_file = test_get_logfile(); 678 679 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 680 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 681 682 my $user = 'proftpd'; 683 my $passwd = 'test'; 684 my $group = 'ftpd'; 685 my $home_dir = File::Spec->rel2abs($tmpdir); 686 my $uid = 500; 687 my $gid = 500; 688 689 # Make sure that, if we're running as root, that the home directory has 690 # permissions/privs set for the account we create 691 if ($< == 0) { 692 unless (chmod(0755, $home_dir)) { 693 die("Can't set perms on $home_dir to 0755: $!"); 694 } 695 696 unless (chown($uid, $gid, $home_dir)) { 697 die("Can't set owner of $home_dir to $uid/$gid: $!"); 698 } 699 } 700 701 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 702 '/bin/bash'); 703 auth_group_write($auth_group_file, $group, $gid, $user); 704 705 my $config = { 706 PidFile => $pid_file, 707 ScoreboardFile => $scoreboard_file, 708 SystemLog => $log_file, 709 710 AuthUserFile => "$auth_user_file name ^3133tH\@x0R\$", 711 AuthGroupFile => $auth_group_file, 712 713 IfModules => { 714 'mod_delay.c' => { 715 DelayEngine => 'off', 716 }, 717 }, 718 }; 719 720 my ($port, $config_user, $config_group) = config_write($config_file, $config); 721 722 # Open pipes, for use between the parent and child processes. Specifically, 723 # the child will indicate when it's done with its test by writing a message 724 # to the parent. 725 my ($rfh, $wfh); 726 unless (pipe($rfh, $wfh)) { 727 die("Can't open pipe: $!"); 728 } 729 730 my $ex; 731 732 # Fork child 733 $self->handle_sigchld(); 734 defined(my $pid = fork()) or die("Can't fork: $!"); 735 if ($pid) { 736 eval { 737 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 738 eval { $client->login($user, $passwd) }; 739 unless ($@) { 740 die("Login succeeded unexpectedly"); 741 } 742 743 $client->quit(); 744 }; 745 746 if ($@) { 747 $ex = $@; 748 } 749 750 $wfh->print("done\n"); 751 $wfh->flush(); 752 753 } else { 754 eval { server_wait($config_file, $rfh) }; 755 if ($@) { 756 warn($@); 757 exit 1; 758 } 759 760 exit 0; 761 } 762 763 # Stop server 764 server_stop($pid_file); 765 766 $self->assert_child_ok($pid); 767 768 if ($ex) { 769 test_append_logfile($log_file, $ex); 770 unlink($log_file); 771 772 die($ex); 773 } 774 775 unlink($log_file); 776} 777 778sub auth_group_file_id_range_ok { 779 my $self = shift; 780 my $tmpdir = $self->{tmpdir}; 781 782 my $config_file = "$tmpdir/authfile.conf"; 783 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 784 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 785 786 my $log_file = test_get_logfile(); 787 788 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 789 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 790 791 my $user = 'proftpd'; 792 my $passwd = 'test'; 793 my $group = 'ftpd'; 794 my $home_dir = File::Spec->rel2abs($tmpdir); 795 my $uid = 500; 796 my $gid = 500; 797 798 # Make sure that, if we're running as root, that the home directory has 799 # permissions/privs set for the account we create 800 if ($< == 0) { 801 unless (chmod(0755, $home_dir)) { 802 die("Can't set perms on $home_dir to 0755: $!"); 803 } 804 805 unless (chown($uid, $gid, $home_dir)) { 806 die("Can't set owner of $home_dir to $uid/$gid: $!"); 807 } 808 } 809 810 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 811 '/bin/bash'); 812 auth_group_write($auth_group_file, $group, $gid, $user); 813 814 my $config = { 815 PidFile => $pid_file, 816 ScoreboardFile => $scoreboard_file, 817 SystemLog => $log_file, 818 819 AuthUserFile => $auth_user_file, 820 AuthGroupFile => "$auth_group_file id 100-500", 821 822 IfModules => { 823 'mod_delay.c' => { 824 DelayEngine => 'off', 825 }, 826 }, 827 }; 828 829 my ($port, $config_user, $config_group) = config_write($config_file, $config); 830 831 if (open(my $fh, ">> $config_file")) { 832 print $fh <<EOC; 833<Limit LOGIN> 834 AllowGroup $group 835 DenyAll 836</Limit> 837EOC 838 839 unless (close($fh)) { 840 die("Can't write $config_file: $!"); 841 } 842 843 } else { 844 die("Can't open $config_file: $!"); 845 } 846 847 # Open pipes, for use between the parent and child processes. Specifically, 848 # the child will indicate when it's done with its test by writing a message 849 # to the parent. 850 my ($rfh, $wfh); 851 unless (pipe($rfh, $wfh)) { 852 die("Can't open pipe: $!"); 853 } 854 855 my $ex; 856 857 # Fork child 858 $self->handle_sigchld(); 859 defined(my $pid = fork()) or die("Can't fork: $!"); 860 if ($pid) { 861 eval { 862 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 863 $client->login($user, $passwd); 864 $client->quit(); 865 }; 866 867 if ($@) { 868 $ex = $@; 869 } 870 871 $wfh->print("done\n"); 872 $wfh->flush(); 873 874 } else { 875 eval { server_wait($config_file, $rfh) }; 876 if ($@) { 877 warn($@); 878 exit 1; 879 } 880 881 exit 0; 882 } 883 884 # Stop server 885 server_stop($pid_file); 886 887 $self->assert_child_ok($pid); 888 889 if ($ex) { 890 test_append_logfile($log_file, $ex); 891 unlink($log_file); 892 893 die($ex); 894 } 895 896 unlink($log_file); 897} 898 899sub auth_group_file_id_range_failed { 900 my $self = shift; 901 my $tmpdir = $self->{tmpdir}; 902 903 my $config_file = "$tmpdir/authfile.conf"; 904 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 905 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 906 907 my $log_file = test_get_logfile(); 908 909 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 910 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 911 912 my $user = 'proftpd'; 913 my $passwd = 'test'; 914 my $group = 'ftpd'; 915 my $home_dir = File::Spec->rel2abs($tmpdir); 916 my $uid = 1000; 917 my $gid = 1000; 918 919 # Make sure that, if we're running as root, that the home directory has 920 # permissions/privs set for the account we create 921 if ($< == 0) { 922 unless (chmod(0755, $home_dir)) { 923 die("Can't set perms on $home_dir to 0755: $!"); 924 } 925 926 unless (chown($uid, $gid, $home_dir)) { 927 die("Can't set owner of $home_dir to $uid/$gid: $!"); 928 } 929 } 930 931 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 932 '/bin/bash'); 933 auth_group_write($auth_group_file, $group, $gid, $user); 934 935 my $config = { 936 PidFile => $pid_file, 937 ScoreboardFile => $scoreboard_file, 938 SystemLog => $log_file, 939 940 AuthUserFile => $auth_user_file, 941 AuthGroupFile => "$auth_group_file id 100-500", 942 943 IfModules => { 944 'mod_delay.c' => { 945 DelayEngine => 'off', 946 }, 947 }, 948 }; 949 950 my ($port, $config_user, $config_group) = config_write($config_file, $config); 951 952 if (open(my $fh, ">> $config_file")) { 953 print $fh <<EOC; 954<Limit LOGIN> 955 AllowGroup $group 956 DenyAll 957</Limit> 958EOC 959 960 unless (close($fh)) { 961 die("Can't write $config_file: $!"); 962 } 963 964 } else { 965 die("Can't open $config_file: $!"); 966 } 967 968 # Open pipes, for use between the parent and child processes. Specifically, 969 # the child will indicate when it's done with its test by writing a message 970 # to the parent. 971 my ($rfh, $wfh); 972 unless (pipe($rfh, $wfh)) { 973 die("Can't open pipe: $!"); 974 } 975 976 my $ex; 977 978 # Fork child 979 $self->handle_sigchld(); 980 defined(my $pid = fork()) or die("Can't fork: $!"); 981 if ($pid) { 982 eval { 983 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 984 eval { $client->login($user, $passwd) }; 985 unless ($@) { 986 die("Login succeeded unexpectedly"); 987 } 988 989 $client->quit(); 990 }; 991 992 if ($@) { 993 $ex = $@; 994 } 995 996 $wfh->print("done\n"); 997 $wfh->flush(); 998 999 } else { 1000 eval { server_wait($config_file, $rfh) }; 1001 if ($@) { 1002 warn($@); 1003 exit 1; 1004 } 1005 1006 exit 0; 1007 } 1008 1009 # Stop server 1010 server_stop($pid_file); 1011 1012 $self->assert_child_ok($pid); 1013 1014 if ($ex) { 1015 test_append_logfile($log_file, $ex); 1016 unlink($log_file); 1017 1018 die($ex); 1019 } 1020 1021 unlink($log_file); 1022} 1023 1024sub auth_group_file_name_filter_ok { 1025 my $self = shift; 1026 my $tmpdir = $self->{tmpdir}; 1027 1028 my $config_file = "$tmpdir/authfile.conf"; 1029 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1030 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1031 1032 my $log_file = test_get_logfile(); 1033 1034 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1035 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1036 1037 my $user = 'proftpd'; 1038 my $passwd = 'test'; 1039 my $group = 'ftpd'; 1040 my $home_dir = File::Spec->rel2abs($tmpdir); 1041 my $uid = 500; 1042 my $gid = 500; 1043 1044 # Make sure that, if we're running as root, that the home directory has 1045 # permissions/privs set for the account we create 1046 if ($< == 0) { 1047 unless (chmod(0755, $home_dir)) { 1048 die("Can't set perms on $home_dir to 0755: $!"); 1049 } 1050 1051 unless (chown($uid, $gid, $home_dir)) { 1052 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1053 } 1054 } 1055 1056 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1057 '/bin/bash'); 1058 auth_group_write($auth_group_file, $group, $gid, $user); 1059 1060 my $config = { 1061 PidFile => $pid_file, 1062 ScoreboardFile => $scoreboard_file, 1063 SystemLog => $log_file, 1064 1065 AuthUserFile => $auth_user_file, 1066 AuthGroupFile => "$auth_group_file name ^$group\$", 1067 1068 IfModules => { 1069 'mod_delay.c' => { 1070 DelayEngine => 'off', 1071 }, 1072 }, 1073 }; 1074 1075 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1076 1077 if (open(my $fh, ">> $config_file")) { 1078 print $fh <<EOC; 1079<Limit LOGIN> 1080 AllowGroup $group 1081 DenyAll 1082</Limit> 1083EOC 1084 1085 unless (close($fh)) { 1086 die("Can't write $config_file: $!"); 1087 } 1088 1089 } else { 1090 die("Can't open $config_file: $!"); 1091 } 1092 1093 # Open pipes, for use between the parent and child processes. Specifically, 1094 # the child will indicate when it's done with its test by writing a message 1095 # to the parent. 1096 my ($rfh, $wfh); 1097 unless (pipe($rfh, $wfh)) { 1098 die("Can't open pipe: $!"); 1099 } 1100 1101 my $ex; 1102 1103 # Fork child 1104 $self->handle_sigchld(); 1105 defined(my $pid = fork()) or die("Can't fork: $!"); 1106 if ($pid) { 1107 eval { 1108 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1109 $client->login($user, $passwd); 1110 $client->quit(); 1111 }; 1112 1113 if ($@) { 1114 $ex = $@; 1115 } 1116 1117 $wfh->print("done\n"); 1118 $wfh->flush(); 1119 1120 } else { 1121 eval { server_wait($config_file, $rfh) }; 1122 if ($@) { 1123 warn($@); 1124 exit 1; 1125 } 1126 1127 exit 0; 1128 } 1129 1130 # Stop server 1131 server_stop($pid_file); 1132 1133 $self->assert_child_ok($pid); 1134 1135 if ($ex) { 1136 test_append_logfile($log_file, $ex); 1137 unlink($log_file); 1138 1139 die($ex); 1140 } 1141 1142 unlink($log_file); 1143} 1144 1145sub auth_group_file_name_filter_failed { 1146 my $self = shift; 1147 my $tmpdir = $self->{tmpdir}; 1148 1149 my $config_file = "$tmpdir/authfile.conf"; 1150 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1151 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1152 1153 my $log_file = test_get_logfile(); 1154 1155 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1156 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1157 1158 my $user = 'proftpd'; 1159 my $passwd = 'test'; 1160 my $group = 'ftpd'; 1161 my $home_dir = File::Spec->rel2abs($tmpdir); 1162 my $uid = 500; 1163 my $gid = 500; 1164 1165 # Make sure that, if we're running as root, that the home directory has 1166 # permissions/privs set for the account we create 1167 if ($< == 0) { 1168 unless (chmod(0755, $home_dir)) { 1169 die("Can't set perms on $home_dir to 0755: $!"); 1170 } 1171 1172 unless (chown($uid, $gid, $home_dir)) { 1173 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1174 } 1175 } 1176 1177 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1178 '/bin/bash'); 1179 auth_group_write($auth_group_file, $group, $gid, $user); 1180 1181 my $config = { 1182 PidFile => $pid_file, 1183 ScoreboardFile => $scoreboard_file, 1184 SystemLog => $log_file, 1185 1186 AuthUserFile => $auth_user_file, 1187 AuthGroupFile => "$auth_group_file name ^3133tH\@x0R\$", 1188 1189 IfModules => { 1190 'mod_delay.c' => { 1191 DelayEngine => 'off', 1192 }, 1193 }, 1194 }; 1195 1196 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1197 1198 if (open(my $fh, ">> $config_file")) { 1199 print $fh <<EOC; 1200<Limit LOGIN> 1201 AllowGroup $group 1202 DenyAll 1203</Limit> 1204EOC 1205 1206 unless (close($fh)) { 1207 die("Can't write $config_file: $!"); 1208 } 1209 1210 } else { 1211 die("Can't open $config_file: $!"); 1212 } 1213 1214 # Open pipes, for use between the parent and child processes. Specifically, 1215 # the child will indicate when it's done with its test by writing a message 1216 # to the parent. 1217 my ($rfh, $wfh); 1218 unless (pipe($rfh, $wfh)) { 1219 die("Can't open pipe: $!"); 1220 } 1221 1222 my $ex; 1223 1224 # Fork child 1225 $self->handle_sigchld(); 1226 defined(my $pid = fork()) or die("Can't fork: $!"); 1227 if ($pid) { 1228 eval { 1229 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1230 eval { $client->login($user, $passwd) }; 1231 unless ($@) { 1232 die("Login succeeded unexpectedly"); 1233 } 1234 1235 $client->quit(); 1236 }; 1237 1238 if ($@) { 1239 $ex = $@; 1240 } 1241 1242 $wfh->print("done\n"); 1243 $wfh->flush(); 1244 1245 } else { 1246 eval { server_wait($config_file, $rfh) }; 1247 if ($@) { 1248 warn($@); 1249 exit 1; 1250 } 1251 1252 exit 0; 1253 } 1254 1255 # Stop server 1256 server_stop($pid_file); 1257 1258 $self->assert_child_ok($pid); 1259 1260 if ($ex) { 1261 test_append_logfile($log_file, $ex); 1262 unlink($log_file); 1263 1264 die($ex); 1265 } 1266 1267 unlink($log_file); 1268} 1269 1270sub auth_user_file_at_symbol_ok { 1271 my $self = shift; 1272 my $tmpdir = $self->{tmpdir}; 1273 1274 my $config_file = "$tmpdir/authfile.conf"; 1275 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1276 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1277 1278 my $log_file = test_get_logfile(); 1279 1280 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1281 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1282 1283 my $user = 'proftpd@proftpd.org'; 1284 my $passwd = 'test'; 1285 my $group = 'ftpd'; 1286 my $home_dir = File::Spec->rel2abs($tmpdir); 1287 my $uid = 500; 1288 my $gid = 500; 1289 1290 # Make sure that, if we're running as root, that the home directory has 1291 # permissions/privs set for the account we create 1292 if ($< == 0) { 1293 unless (chmod(0755, $home_dir)) { 1294 die("Can't set perms on $home_dir to 0755: $!"); 1295 } 1296 1297 unless (chown($uid, $gid, $home_dir)) { 1298 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1299 } 1300 } 1301 1302 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1303 '/bin/bash'); 1304 auth_group_write($auth_group_file, $group, $gid, $user); 1305 1306 my $config = { 1307 PidFile => $pid_file, 1308 ScoreboardFile => $scoreboard_file, 1309 SystemLog => $log_file, 1310 1311 AuthUserFile => $auth_user_file, 1312 AuthGroupFile => $auth_group_file, 1313 1314 IfModules => { 1315 'mod_delay.c' => { 1316 DelayEngine => 'off', 1317 }, 1318 }, 1319 }; 1320 1321 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1322 1323 # Open pipes, for use between the parent and child processes. Specifically, 1324 # the child will indicate when it's done with its test by writing a message 1325 # to the parent. 1326 my ($rfh, $wfh); 1327 unless (pipe($rfh, $wfh)) { 1328 die("Can't open pipe: $!"); 1329 } 1330 1331 my $ex; 1332 1333 # Fork child 1334 $self->handle_sigchld(); 1335 defined(my $pid = fork()) or die("Can't fork: $!"); 1336 if ($pid) { 1337 eval { 1338 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1339 $client->login($user, $passwd); 1340 $client->quit(); 1341 }; 1342 1343 if ($@) { 1344 $ex = $@; 1345 } 1346 1347 $wfh->print("done\n"); 1348 $wfh->flush(); 1349 1350 } else { 1351 eval { server_wait($config_file, $rfh) }; 1352 if ($@) { 1353 warn($@); 1354 exit 1; 1355 } 1356 1357 exit 0; 1358 } 1359 1360 # Stop server 1361 server_stop($pid_file); 1362 1363 $self->assert_child_ok($pid); 1364 1365 if ($ex) { 1366 test_append_logfile($log_file, $ex); 1367 unlink($log_file); 1368 1369 die($ex); 1370 } 1371 1372 unlink($log_file); 1373} 1374 1375sub auth_user_file_world_readable_bug3892 { 1376 my $self = shift; 1377 my $tmpdir = $self->{tmpdir}; 1378 1379 my $config_file = "$tmpdir/authfile.conf"; 1380 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1381 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1382 1383 my $log_file = test_get_logfile(); 1384 1385 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1386 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1387 1388 my $user = 'proftpd'; 1389 my $passwd = 'test'; 1390 my $group = 'ftpd'; 1391 my $home_dir = File::Spec->rel2abs($tmpdir); 1392 my $uid = 500; 1393 my $gid = 500; 1394 1395 # Make sure that, if we're running as root, that the home directory has 1396 # permissions/privs set for the account we create 1397 if ($< == 0) { 1398 unless (chmod(0755, $home_dir)) { 1399 die("Can't set perms on $home_dir to 0755: $!"); 1400 } 1401 1402 unless (chown($uid, $gid, $home_dir)) { 1403 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1404 } 1405 } 1406 1407 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1408 '/bin/bash'); 1409 auth_group_write($auth_group_file, $group, $gid, $user); 1410 1411 # Deliberately set world-readable perms on the AuthUserFile, to trigger 1412 # the checks done for Bug#3892. 1413 unless (chmod(0444, $auth_user_file)) { 1414 die("Can't set perms on $auth_user_file: $!"); 1415 } 1416 1417 my $config = { 1418 PidFile => $pid_file, 1419 ScoreboardFile => $scoreboard_file, 1420 SystemLog => $log_file, 1421 1422 AuthUserFile => $auth_user_file, 1423 AuthGroupFile => $auth_group_file, 1424 1425 IfModules => { 1426 'mod_delay.c' => { 1427 DelayEngine => 'off', 1428 }, 1429 }, 1430 }; 1431 1432 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1433 1434 eval { server_start($config_file, $pid_file) }; 1435 unless ($@) { 1436 server_stop($pid_file); 1437 1438 my $ex = "Server started up unexpectedly with world-readable AuthUserFile"; 1439 test_append_logfile($log_file, $ex); 1440 unlink($log_file); 1441 1442 die($ex); 1443 } 1444 1445 unlink($log_file); 1446} 1447 1448sub auth_user_file_world_writable_bug3892 { 1449 my $self = shift; 1450 my $tmpdir = $self->{tmpdir}; 1451 1452 my $config_file = "$tmpdir/authfile.conf"; 1453 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1454 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1455 1456 my $log_file = test_get_logfile(); 1457 1458 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1459 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1460 1461 my $user = 'proftpd'; 1462 my $passwd = 'test'; 1463 my $group = 'ftpd'; 1464 my $home_dir = File::Spec->rel2abs($tmpdir); 1465 my $uid = 500; 1466 my $gid = 500; 1467 1468 # Make sure that, if we're running as root, that the home directory has 1469 # permissions/privs set for the account we create 1470 if ($< == 0) { 1471 unless (chmod(0755, $home_dir)) { 1472 die("Can't set perms on $home_dir to 0755: $!"); 1473 } 1474 1475 unless (chown($uid, $gid, $home_dir)) { 1476 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1477 } 1478 } 1479 1480 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1481 '/bin/bash'); 1482 auth_group_write($auth_group_file, $group, $gid, $user); 1483 1484 # Deliberately set world-writable perms on the AuthUserFile, to trigger 1485 # the checks done for Bug#3892. 1486 unless (chmod(0442, $auth_user_file)) { 1487 die("Can't set perms on $auth_user_file: $!"); 1488 } 1489 1490 my $config = { 1491 PidFile => $pid_file, 1492 ScoreboardFile => $scoreboard_file, 1493 SystemLog => $log_file, 1494 1495 AuthUserFile => $auth_user_file, 1496 AuthGroupFile => $auth_group_file, 1497 1498 IfModules => { 1499 'mod_delay.c' => { 1500 DelayEngine => 'off', 1501 }, 1502 }, 1503 }; 1504 1505 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1506 1507 eval { server_start($config_file, $pid_file) }; 1508 unless ($@) { 1509 server_stop($pid_file); 1510 1511 my $ex = "Server started up unexpectedly with world-writable AuthUserFile"; 1512 test_append_logfile($log_file, $ex); 1513 unlink($log_file); 1514 1515 die($ex); 1516 } 1517 1518 unlink($log_file); 1519} 1520 1521sub auth_user_file_world_readable_insecure_perms_opt { 1522 my $self = shift; 1523 my $tmpdir = $self->{tmpdir}; 1524 my $setup = test_setup($tmpdir, 'authfile'); 1525 1526 # Deliberately set world-readable perms on the AuthUserFile, to trigger 1527 # the checks done for Bug#3892. 1528 unless (chmod(0444, $setup->{auth_user_file})) { 1529 die("Can't set perms on $setup->{auth_user_file}: $!"); 1530 } 1531 1532 my $config = { 1533 PidFile => $setup->{pid_file}, 1534 ScoreboardFile => $setup->{scoreboard_file}, 1535 SystemLog => $setup->{log_file}, 1536 1537 IfModules => { 1538 'mod_delay.c' => { 1539 DelayEngine => 'off', 1540 }, 1541 }, 1542 }; 1543 1544 my ($port, $config_user, $config_group) = config_write($setup->{config_file}, 1545 $config); 1546 1547 # Note that we set this AuthFileOption here using an array, so that the 1548 # order of the directives is deterministic! 1549 if (open(my $fh, ">> $setup->{config_file}")) { 1550 print $fh <<EOC; 1551AuthFileOptions InsecurePerms 1552AuthUserFile $setup->{auth_user_file} 1553AuthGroupFile $setup->{auth_group_file} 1554EOC 1555 unless (close($fh)) { 1556 die("Can't write $setup->{config_file}: $!"); 1557 } 1558 1559 } else { 1560 die("Can't open $setup->{config_file}: $!"); 1561 } 1562 1563 my $ex; 1564 1565 eval { server_start($setup->{config_file}, $setup->{pid_file}) }; 1566 if ($@) { 1567 $ex = $@; 1568 1569 } else { 1570 server_stop($setup->{pid_file}); 1571 } 1572 1573 test_cleanup($setup->{log_file}, $ex); 1574} 1575 1576sub auth_group_file_world_readable_bug3892 { 1577 my $self = shift; 1578 my $tmpdir = $self->{tmpdir}; 1579 1580 my $config_file = "$tmpdir/authfile.conf"; 1581 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1582 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1583 1584 my $log_file = test_get_logfile(); 1585 1586 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1587 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1588 1589 my $user = 'proftpd'; 1590 my $passwd = 'test'; 1591 my $group = 'ftpd'; 1592 my $home_dir = File::Spec->rel2abs($tmpdir); 1593 my $uid = 500; 1594 my $gid = 500; 1595 1596 # Make sure that, if we're running as root, that the home directory has 1597 # permissions/privs set for the account we create 1598 if ($< == 0) { 1599 unless (chmod(0755, $home_dir)) { 1600 die("Can't set perms on $home_dir to 0755: $!"); 1601 } 1602 1603 unless (chown($uid, $gid, $home_dir)) { 1604 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1605 } 1606 } 1607 1608 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1609 '/bin/bash'); 1610 auth_group_write($auth_group_file, $group, $gid, $user); 1611 1612 # Deliberately set world-readable perms on the AuthGroupFile, to trigger 1613 # the checks done for Bug#3892. 1614 unless (chmod(0444, $auth_group_file)) { 1615 die("Can't set perms on $auth_group_file: $!"); 1616 } 1617 1618 my $config = { 1619 PidFile => $pid_file, 1620 ScoreboardFile => $scoreboard_file, 1621 SystemLog => $log_file, 1622 1623 AuthUserFile => $auth_user_file, 1624 AuthGroupFile => $auth_group_file, 1625 1626 IfModules => { 1627 'mod_delay.c' => { 1628 DelayEngine => 'off', 1629 }, 1630 }, 1631 }; 1632 1633 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1634 1635 eval { server_start($config_file, $pid_file) }; 1636 if ($@) { 1637 my $ex = $@; 1638 test_append_logfile($log_file, $ex); 1639 unlink($log_file); 1640 1641 die($ex); 1642 } 1643 1644 server_stop($pid_file); 1645 unlink($log_file); 1646} 1647 1648sub auth_group_file_world_writable_bug3892 { 1649 my $self = shift; 1650 my $tmpdir = $self->{tmpdir}; 1651 1652 my $config_file = "$tmpdir/authfile.conf"; 1653 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1654 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1655 1656 my $log_file = test_get_logfile(); 1657 1658 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1659 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1660 1661 my $user = 'proftpd'; 1662 my $passwd = 'test'; 1663 my $group = 'ftpd'; 1664 my $home_dir = File::Spec->rel2abs($tmpdir); 1665 my $uid = 500; 1666 my $gid = 500; 1667 1668 # Make sure that, if we're running as root, that the home directory has 1669 # permissions/privs set for the account we create 1670 if ($< == 0) { 1671 unless (chmod(0755, $home_dir)) { 1672 die("Can't set perms on $home_dir to 0755: $!"); 1673 } 1674 1675 unless (chown($uid, $gid, $home_dir)) { 1676 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1677 } 1678 } 1679 1680 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1681 '/bin/bash'); 1682 auth_group_write($auth_group_file, $group, $gid, $user); 1683 1684 # Deliberately set world-writable perms on the AuthGroupFile, to trigger 1685 # the checks done for Bug#3892. 1686 unless (chmod(0442, $auth_group_file)) { 1687 die("Can't set perms on $auth_group_file: $!"); 1688 } 1689 1690 my $config = { 1691 PidFile => $pid_file, 1692 ScoreboardFile => $scoreboard_file, 1693 SystemLog => $log_file, 1694 1695 AuthUserFile => $auth_user_file, 1696 AuthGroupFile => $auth_group_file, 1697 1698 IfModules => { 1699 'mod_delay.c' => { 1700 DelayEngine => 'off', 1701 }, 1702 }, 1703 }; 1704 1705 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1706 1707 eval { server_start($config_file, $pid_file) }; 1708 unless ($@) { 1709 server_stop($pid_file); 1710 1711 my $ex = "Server started up unexpectedly with world-writable AuthGroupFile"; 1712 test_append_logfile($log_file, $ex); 1713 unlink($log_file); 1714 1715 die($ex); 1716 } 1717 1718 unlink($log_file); 1719} 1720 1721sub auth_user_file_world_writable_parent_dir_bug3892 { 1722 my $self = shift; 1723 my $tmpdir = $self->{tmpdir}; 1724 1725 my $config_file = "$tmpdir/authfile.conf"; 1726 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1727 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1728 1729 my $log_file = test_get_logfile(); 1730 1731 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1732 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1733 1734 my $user = 'proftpd'; 1735 my $passwd = 'test'; 1736 my $group = 'ftpd'; 1737 my $home_dir = File::Spec->rel2abs($tmpdir); 1738 my $uid = 500; 1739 my $gid = 500; 1740 1741 # Make sure that, if we're running as root, that the home directory has 1742 # permissions/privs set for the account we create 1743 if ($< == 0) { 1744 unless (chmod(0755, $home_dir)) { 1745 die("Can't set perms on $home_dir to 0755: $!"); 1746 } 1747 1748 unless (chown($uid, $gid, $home_dir)) { 1749 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1750 } 1751 } 1752 1753 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1754 '/bin/bash'); 1755 auth_group_write($auth_group_file, $group, $gid, $user); 1756 1757 # Deliberately set world-writable perms on the parent directory of the 1758 # AuthUserFile, to trigger the checks done for Bug#3892. 1759 unless (chmod(0777, $tmpdir)) { 1760 die("Can't set perms on $tmpdir: $!"); 1761 } 1762 1763 my $config = { 1764 PidFile => $pid_file, 1765 ScoreboardFile => $scoreboard_file, 1766 SystemLog => $log_file, 1767 1768 AuthUserFile => $auth_user_file, 1769 AuthGroupFile => $auth_group_file, 1770 1771 IfModules => { 1772 'mod_delay.c' => { 1773 DelayEngine => 'off', 1774 }, 1775 }, 1776 }; 1777 1778 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1779 1780 eval { server_start($config_file, $pid_file) }; 1781 unless ($@) { 1782 server_stop($pid_file); 1783 1784 my $ex = "Server started up unexpectedly with world-writable AuthUserFile parent directory"; 1785 test_append_logfile($log_file, $ex); 1786 unlink($log_file); 1787 1788 die($ex); 1789 } 1790 1791 unlink($log_file); 1792} 1793 1794sub auth_user_file_symlink_world_writable_parent_dir_bug3892 { 1795 my $self = shift; 1796 my $tmpdir = $self->{tmpdir}; 1797 1798 my $config_file = "$tmpdir/authfile.conf"; 1799 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1800 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1801 1802 my $log_file = test_get_logfile(); 1803 1804 my $etc_dir = File::Spec->rel2abs("$tmpdir/etc"); 1805 mkpath($etc_dir); 1806 1807 my $auth_user_file = File::Spec->rel2abs("$tmpdir/etc/authfile.passwd"); 1808 my $auth_group_file = File::Spec->rel2abs("$tmpdir/etc/authfile.group"); 1809 1810 my $user = 'proftpd'; 1811 my $passwd = 'test'; 1812 my $group = 'ftpd'; 1813 my $home_dir = File::Spec->rel2abs($tmpdir); 1814 my $uid = 500; 1815 my $gid = 500; 1816 1817 my $test_dir = File::Spec->rel2abs("$tmpdir/test.d"); 1818 mkpath($test_dir); 1819 my $auth_user_symlink = File::Spec->rel2abs("$tmpdir/test.d/authfile.lnk"); 1820 1821 # Make sure that, if we're running as root, that the home directory has 1822 # permissions/privs set for the account we create 1823 # 1824 # Deliberately set world-writable perms on the symlink parent 1825 # directory, to trigger the checks done for Bug#3892. 1826 1827 if ($< == 0) { 1828 unless (chmod(0750, $home_dir, $etc_dir)) { 1829 die("Can't set perms on $home_dir to 0750: $!"); 1830 } 1831 1832 unless (chmod(0777, $test_dir)) { 1833 die("Can't set perms on $etc_dir to 0777: $!"); 1834 } 1835 1836 unless (chown($uid, $gid, $home_dir, $etc_dir, $test_dir)) { 1837 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1838 } 1839 1840 } else { 1841 unless (chmod(0750, $home_dir, $etc_dir)) { 1842 die("Can't set perms on $home_dir to 0750: $!"); 1843 } 1844 1845 unless (chmod(0777, $test_dir)) { 1846 die("Can't set perms on $test_dir to 0777: $!"); 1847 } 1848 } 1849 1850 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1851 '/bin/bash'); 1852 auth_group_write($auth_group_file, $group, $gid, $user); 1853 1854 my $cwd = getcwd(); 1855 unless (chdir($test_dir)) { 1856 die("Can't chdir to $test_dir: $!"); 1857 } 1858 1859 unless (symlink($auth_user_file, 'authfile.lnk')) { 1860 die("Can't symlink '$auth_user_file' to 'authfile.lnk': $!"); 1861 } 1862 1863 unless (chdir($cwd)) { 1864 die("Can't chdir to $cwd: $!"); 1865 } 1866 1867 my $config = { 1868 PidFile => $pid_file, 1869 ScoreboardFile => $scoreboard_file, 1870 SystemLog => $log_file, 1871 1872 AuthUserFile => $auth_user_symlink, 1873 AuthGroupFile => $auth_group_file, 1874 1875 IfModules => { 1876 'mod_delay.c' => { 1877 DelayEngine => 'off', 1878 }, 1879 }, 1880 }; 1881 1882 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1883 1884 eval { server_start($config_file, $pid_file) }; 1885 unless ($@) { 1886 server_stop($pid_file); 1887 1888 my $ex = "Server started up unexpectedly with symlink AuthUserFile"; 1889 test_append_logfile($log_file, $ex); 1890 unlink($log_file); 1891 1892 die($ex); 1893 } 1894 1895 unlink($log_file); 1896} 1897 1898sub auth_user_file_bad_syntax_bug3985 { 1899 my $self = shift; 1900 my $tmpdir = $self->{tmpdir}; 1901 1902 my $config_file = "$tmpdir/authfile.conf"; 1903 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 1904 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 1905 1906 my $log_file = test_get_logfile(); 1907 1908 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 1909 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 1910 1911 my $user = 'proftpd'; 1912 my $passwd = 'test'; 1913 my $group = 'ftpd'; 1914 my $home_dir = File::Spec->rel2abs($tmpdir); 1915 my $uid = 500; 1916 my $gid = 500; 1917 1918 # Make sure that, if we're running as root, that the home directory has 1919 # permissions/privs set for the account we create 1920 if ($< == 0) { 1921 unless (chmod(0755, $home_dir)) { 1922 die("Can't set perms on $home_dir to 0755: $!"); 1923 } 1924 1925 unless (chown($uid, $gid, $home_dir)) { 1926 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1927 } 1928 } 1929 1930 # Test that mod_auth_file correctly deals with malformed AuthUserFile 1931 # entries (per Bug#3985). 1932 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1933 '/bin/bash', "FirstName:LastName"); 1934 1935 auth_group_write($auth_group_file, $group, $gid, $user); 1936 1937 my $config = { 1938 PidFile => $pid_file, 1939 ScoreboardFile => $scoreboard_file, 1940 SystemLog => $log_file, 1941 1942 AuthUserFile => $auth_user_file, 1943 AuthGroupFile => $auth_group_file, 1944 1945 IfModules => { 1946 'mod_delay.c' => { 1947 DelayEngine => 'off', 1948 }, 1949 }, 1950 }; 1951 1952 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1953 1954 # Open pipes, for use between the parent and child processes. Specifically, 1955 # the child will indicate when it's done with its test by writing a message 1956 # to the parent. 1957 my ($rfh, $wfh); 1958 unless (pipe($rfh, $wfh)) { 1959 die("Can't open pipe: $!"); 1960 } 1961 1962 my $ex; 1963 1964 # Fork child 1965 $self->handle_sigchld(); 1966 defined(my $pid = fork()) or die("Can't fork: $!"); 1967 if ($pid) { 1968 eval { 1969 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1970 eval { $client->login($user, $passwd) }; 1971 unless ($@) { 1972 $client->quit(); 1973 die("Login succeeded unexpectedly"); 1974 } 1975 }; 1976 1977 if ($@) { 1978 $ex = $@; 1979 } 1980 1981 $wfh->print("done\n"); 1982 $wfh->flush(); 1983 1984 } else { 1985 eval { server_wait($config_file, $rfh) }; 1986 if ($@) { 1987 warn($@); 1988 exit 1; 1989 } 1990 1991 exit 0; 1992 } 1993 1994 # Stop server 1995 server_stop($pid_file); 1996 1997 $self->assert_child_ok($pid); 1998 1999 if ($ex) { 2000 test_append_logfile($log_file, $ex); 2001 unlink($log_file); 2002 2003 die($ex); 2004 } 2005 2006 unlink($log_file); 2007} 2008 2009sub auth_group_file_bad_syntax_bug3985 { 2010 my $self = shift; 2011 my $tmpdir = $self->{tmpdir}; 2012 2013 my $config_file = "$tmpdir/authfile.conf"; 2014 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 2015 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 2016 2017 my $log_file = test_get_logfile(); 2018 2019 my $auth_user_file = File::Spec->rel2abs("$tmpdir/authfile.passwd"); 2020 my $auth_group_file = File::Spec->rel2abs("$tmpdir/authfile.group"); 2021 2022 my $user = 'proftpd'; 2023 my $passwd = 'test'; 2024 my $group = 'ftpd'; 2025 my $home_dir = File::Spec->rel2abs($tmpdir); 2026 my $uid = 500; 2027 my $gid = 500; 2028 2029 # Make sure that, if we're running as root, that the home directory has 2030 # permissions/privs set for the account we create 2031 if ($< == 0) { 2032 unless (chmod(0755, $home_dir)) { 2033 die("Can't set perms on $home_dir to 0755: $!"); 2034 } 2035 2036 unless (chown($uid, $gid, $home_dir)) { 2037 die("Can't set owner of $home_dir to $uid/$gid: $!"); 2038 } 2039 } 2040 2041 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 2042 '/bin/bash'); 2043 2044 # Test that mod_auth_file correctly deals with malformed AuthGroupFile 2045 # entries (per Bug#3985). 2046 auth_group_write($auth_group_file, "yarr:$group", $gid, $user); 2047 2048 my $config = { 2049 PidFile => $pid_file, 2050 ScoreboardFile => $scoreboard_file, 2051 SystemLog => $log_file, 2052 2053 AuthUserFile => $auth_user_file, 2054 AuthGroupFile => $auth_group_file, 2055 2056 IfModules => { 2057 'mod_delay.c' => { 2058 DelayEngine => 'off', 2059 }, 2060 }, 2061 }; 2062 2063 my ($port, $config_user, $config_group) = config_write($config_file, $config); 2064 2065 if (open(my $fh, ">> $config_file")) { 2066 print $fh <<EOC; 2067<Limit LOGIN> 2068 DenyGroup $group 2069 AllowAll 2070</Limit> 2071EOC 2072 2073 unless (close($fh)) { 2074 die("Can't write $config_file: $!"); 2075 } 2076 2077 } else { 2078 die("Can't open $config_file: $!"); 2079 } 2080 2081 # Open pipes, for use between the parent and child processes. Specifically, 2082 # the child will indicate when it's done with its test by writing a message 2083 # to the parent. 2084 my ($rfh, $wfh); 2085 unless (pipe($rfh, $wfh)) { 2086 die("Can't open pipe: $!"); 2087 } 2088 2089 my $ex; 2090 2091 # Fork child 2092 $self->handle_sigchld(); 2093 defined(my $pid = fork()) or die("Can't fork: $!"); 2094 if ($pid) { 2095 eval { 2096 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 2097 2098 # Despite the <Limit LOGIN> line for our group, we should still 2099 # succeed in logging in, because of the malformed AuthGroupFile 2100 # entry. 2101 $client->login($user, $passwd); 2102 2103 $client->quit(); 2104 }; 2105 2106 if ($@) { 2107 $ex = $@; 2108 } 2109 2110 $wfh->print("done\n"); 2111 $wfh->flush(); 2112 2113 } else { 2114 eval { server_wait($config_file, $rfh) }; 2115 if ($@) { 2116 warn($@); 2117 exit 1; 2118 } 2119 2120 exit 0; 2121 } 2122 2123 # Stop server 2124 server_stop($pid_file); 2125 2126 $self->assert_child_ok($pid); 2127 2128 if ($ex) { 2129 test_append_logfile($log_file, $ex); 2130 unlink($log_file); 2131 2132 die($ex); 2133 } 2134 2135 unlink($log_file); 2136} 2137 2138sub auth_file_symlink_segfault_bug4145 { 2139 my $self = shift; 2140 my $tmpdir = $self->{tmpdir}; 2141 2142 my $config_file = "$tmpdir/authfile.conf"; 2143 my $pid_file = File::Spec->rel2abs("$tmpdir/authfile.pid"); 2144 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/authfile.scoreboard"); 2145 2146 my $log_file = test_get_logfile(); 2147 2148 my $authfiles_parent_dir = File::Spec->rel2abs("$tmpdir/etc"); 2149 mkpath($authfiles_parent_dir); 2150 2151 my $authfiles_dir = File::Spec->rel2abs("$authfiles_parent_dir/proftpd"); 2152 mkpath($authfiles_dir); 2153 2154 my $auth_user_file = File::Spec->rel2abs("$authfiles_dir/authfile.passwd"); 2155 my $auth_group_file = File::Spec->rel2abs("$authfiles_dir/authfile.group"); 2156 2157 # Create symlinks using a relative path to the Auth files, to reproduce 2158 # Bug#4145. 2159 my $cwd = getcwd(); 2160 unless (chdir($authfiles_dir)) { 2161 die("Can't chdir to $authfiles_dir: $!"); 2162 } 2163 2164 unless (symlink('authfile.passwd', "passwd.lnk")) { 2165 die("Can't symlink '$auth_user_file' to 'passwd.lnk': $!"); 2166 } 2167 2168 unless (symlink('authfile.group', "group.lnk")) { 2169 die("Can't symlink '$auth_group_file' to 'group.lnk': $!"); 2170 } 2171 2172 unless (chdir($cwd)) { 2173 die("Can't chdir to $cwd: $!"); 2174 } 2175 2176 my $auth_user_symlink = File::Spec->rel2abs($authfiles_dir) . "/passwd.lnk"; 2177 my $auth_group_symlink = File::Spec->rel2abs($authfiles_dir) . "/group.lnk"; 2178 2179 my $user = 'proftpd'; 2180 my $passwd = 'test'; 2181 my $group = 'ftpd'; 2182 my $home_dir = File::Spec->rel2abs($tmpdir); 2183 my $uid = 500; 2184 my $gid = 500; 2185 2186 # Make sure that, if we're running as root, that the home directory has 2187 # permissions/privs set for the account we create 2188 if ($< == 0) { 2189 unless (chmod(0755, $home_dir, $authfiles_parent_dir, $authfiles_dir)) { 2190 die("Can't set perms on $home_dir to 0755: $!"); 2191 } 2192 2193 unless (chown($uid, $gid, $home_dir, $authfiles_parent_dir, $authfiles_dir)) { 2194 die("Can't set owner of $home_dir to $uid/$gid: $!"); 2195 } 2196 } 2197 2198 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 2199 '/bin/bash'); 2200 2201 # Test that mod_auth_file correctly deals with malformed AuthGroupFile 2202 # entries (per Bug#3985). 2203 auth_group_write($auth_group_file, "yarr:$group", $gid, $user); 2204 2205 my $config = { 2206 PidFile => $pid_file, 2207 ScoreboardFile => $scoreboard_file, 2208 SystemLog => $log_file, 2209 2210 AuthUserFile => $auth_user_symlink, 2211 AuthGroupFile => $auth_group_symlink, 2212 2213 IfModules => { 2214 'mod_delay.c' => { 2215 DelayEngine => 'off', 2216 }, 2217 }, 2218 }; 2219 2220 my ($port, $config_user, $config_group) = config_write($config_file, $config); 2221 2222 # Open pipes, for use between the parent and child processes. Specifically, 2223 # the child will indicate when it's done with its test by writing a message 2224 # to the parent. 2225 my ($rfh, $wfh); 2226 unless (pipe($rfh, $wfh)) { 2227 die("Can't open pipe: $!"); 2228 } 2229 2230 my $ex; 2231 2232 # Fork child 2233 $self->handle_sigchld(); 2234 defined(my $pid = fork()) or die("Can't fork: $!"); 2235 if ($pid) { 2236 eval { 2237 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 2238 $client->login($user, $passwd); 2239 $client->quit(); 2240 }; 2241 2242 if ($@) { 2243 $ex = $@; 2244 } 2245 2246 $wfh->print("done\n"); 2247 $wfh->flush(); 2248 2249 } else { 2250 eval { server_wait($config_file, $rfh) }; 2251 if ($@) { 2252 warn($@); 2253 exit 1; 2254 } 2255 2256 exit 0; 2257 } 2258 2259 # Stop server 2260 server_stop($pid_file); 2261 2262 $self->assert_child_ok($pid); 2263 2264 if ($ex) { 2265 test_append_logfile($log_file, $ex); 2266 unlink($log_file); 2267 2268 die($ex); 2269 } 2270 2271 unlink($log_file); 2272} 2273 22741; 2275