1package ProFTPD::Tests::Logins; 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 login_plaintext_fails_bad_password => { 21 order => ++$order, 22 test_class => [qw(forking)], 23 }, 24 25 login_plaintext_fails_empty_password_bug4139 => { 26 order => ++$order, 27 test_class => [qw(bug forking)], 28 }, 29 30 login_anonymous_ok => { 31 order => ++$order, 32 test_class => [qw(forking rootprivs)], 33 }, 34 35 login_anonymous_with_delay_ok => { 36 order => ++$order, 37 test_class => [qw(forking rootprivs)], 38 }, 39 40 login_anonymous_user_alias_ok => { 41 order => ++$order, 42 test_class => [qw(forking rootprivs)], 43 }, 44 45 login_anonymous_fails_bad_perms => { 46 order => ++$order, 47 test_class => [qw(forking)], 48 }, 49 50 login_anonymous_fails_empty_password_bug4139 => { 51 order => ++$order, 52 test_class => [qw(bug forking)], 53 }, 54 55 login_anonymous_symlink_dir_ok => { 56 order => ++$order, 57 test_class => [qw(forking rootprivs)], 58 }, 59 60 login_anonymous_allowchrootsymlinks_bug3852 => { 61 order => ++$order, 62 test_class => [qw(bug forking rootprivs)], 63 }, 64 65 login_multiple_attempts_per_conn => { 66 order => ++$order, 67 test_class => [qw(forking)], 68 }, 69 70 login_regular_with_anon_defined_bug3307 => { 71 order => ++$order, 72 test_class => [qw(bug forking)], 73 }, 74 75 login_fails_bad_sequence => { 76 order => ++$order, 77 test_class => [qw(forking)], 78 }, 79 80 login_reauthenticate_fails_bug3736 => { 81 order => ++$order, 82 test_class => [qw(bug forking)], 83 }, 84 85 login_reauthenticate_ok_same_user_bug4217 => { 86 order => ++$order, 87 test_class => [qw(bug forking)], 88 }, 89 90 login_reauthenticate_fails_different_user_bug4217 => { 91 order => ++$order, 92 test_class => [qw(bug forking)], 93 }, 94 95 login_reauthenticate_fails_extra_pass_bug4217 => { 96 order => ++$order, 97 test_class => [qw(bug forking)], 98 }, 99 100}; 101 102sub new { 103 return shift()->SUPER::new(@_); 104} 105 106sub list_tests { 107 return testsuite_get_runnable_tests($TESTS); 108} 109 110sub login_plaintext_fails_bad_password { 111 my $self = shift; 112 my $tmpdir = $self->{tmpdir}; 113 114 my $config_file = "$tmpdir/login.conf"; 115 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 116 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 117 118 my $log_file = test_get_logfile(); 119 120 my $config = { 121 PidFile => $pid_file, 122 ScoreboardFile => $scoreboard_file, 123 SystemLog => $log_file, 124 125 IfModules => { 126 'mod_delay.c' => { 127 DelayEngine => 'off', 128 }, 129 }, 130 }; 131 132 my ($port, $user, $group) = config_write($config_file, $config); 133 134 # Open pipes, for use between the parent and child processes. Specifically, 135 # the child will indicate when it's done with its test by writing a message 136 # to the parent. 137 my ($rfh, $wfh); 138 unless (pipe($rfh, $wfh)) { 139 die("Can't open pipe: $!"); 140 } 141 142 my $ex; 143 144 # Fork child 145 $self->handle_sigchld(); 146 defined(my $pid = fork()) or die("Can't fork: $!"); 147 if ($pid) { 148 eval { 149 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 150 151 # In parent process, login to server using a plaintext password which 152 # should NOT work. 153 eval { $client->login('daemon', '*') }; 154 unless ($@) { 155 die("Logged in unexpectedly"); 156 } 157 }; 158 159 if ($@) { 160 $ex = $@; 161 } 162 163 $wfh->print("done\n"); 164 $wfh->flush(); 165 166 } else { 167 eval { server_wait($config_file, $rfh) }; 168 if ($@) { 169 warn($@); 170 exit 1; 171 } 172 173 exit 0; 174 } 175 176 # Stop server 177 server_stop($pid_file); 178 179 $self->assert_child_ok($pid); 180 181 if ($ex) { 182 test_append_logfile($log_file, $ex); 183 unlink($log_file); 184 185 die($ex); 186 } 187 188 unlink($log_file); 189} 190 191sub login_plaintext_fails_empty_password_bug4139 { 192 my $self = shift; 193 my $tmpdir = $self->{tmpdir}; 194 195 my $config_file = "$tmpdir/login.conf"; 196 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 197 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 198 199 my $log_file = test_get_logfile(); 200 201 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 202 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 203 204 my $user = 'proftpd'; 205 my $passwd = ''; 206 my $group = 'ftpd'; 207 my $home_dir = File::Spec->rel2abs($tmpdir); 208 my $uid = 500; 209 my $gid = 500; 210 211 # Make sure that, if we're running as root, that the home directory has 212 # permissions/privs set for the account we create 213 if ($< == 0) { 214 unless (chmod(0755, $home_dir)) { 215 die("Can't set perms on $home_dir to 0755: $!"); 216 } 217 218 unless (chown($uid, $gid, $home_dir)) { 219 die("Can't set owner of $home_dir to $uid/$gid: $!"); 220 } 221 } 222 223 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 224 '/bin/bash'); 225 auth_group_write($auth_group_file, $group, $gid, $user); 226 227 my $config = { 228 PidFile => $pid_file, 229 ScoreboardFile => $scoreboard_file, 230 SystemLog => $log_file, 231 232 AuthUserFile => $auth_user_file, 233 AuthGroupFile => $auth_group_file, 234 235 AllowEmptyPasswords => 'off', 236 237 IfModules => { 238 'mod_delay.c' => { 239 DelayEngine => 'off', 240 }, 241 }, 242 }; 243 244 my ($port, $config_user, $config_group) = config_write($config_file, $config); 245 246 # Open pipes, for use between the parent and child processes. Specifically, 247 # the child will indicate when it's done with its test by writing a message 248 # to the parent. 249 my ($rfh, $wfh); 250 unless (pipe($rfh, $wfh)) { 251 die("Can't open pipe: $!"); 252 } 253 254 my $ex; 255 256 # Fork child 257 $self->handle_sigchld(); 258 defined(my $pid = fork()) or die("Can't fork: $!"); 259 if ($pid) { 260 eval { 261 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 262 eval { $client->login($user, $passwd) }; 263 unless ($@) { 264 die("Logged in unexpectedly"); 265 } 266 267 my $resp_code = $client->response_code(); 268 my $resp_msg = $client->response_msg(); 269 270 my $expected; 271 272 $expected = 501; 273 $self->assert($expected == $resp_code, 274 test_msg("Expected response code $expected, got $resp_code")); 275 276 $expected = 'Login incorrect.'; 277 $self->assert($expected eq $resp_msg, 278 test_msg("Expected response message '$expected', got '$resp_msg'")); 279 280 $client->quit(); 281 }; 282 283 if ($@) { 284 $ex = $@; 285 } 286 287 $wfh->print("done\n"); 288 $wfh->flush(); 289 290 } else { 291 eval { server_wait($config_file, $rfh) }; 292 if ($@) { 293 warn($@); 294 exit 1; 295 } 296 297 exit 0; 298 } 299 300 # Stop server 301 server_stop($pid_file); 302 303 $self->assert_child_ok($pid); 304 305 if ($ex) { 306 test_append_logfile($log_file, $ex); 307 unlink($log_file); 308 309 die($ex); 310 } 311 312 unlink($log_file); 313} 314 315sub login_anonymous_ok { 316 my $self = shift; 317 my $tmpdir = $self->{tmpdir}; 318 319 my $config_file = "$tmpdir/login.conf"; 320 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 321 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 322 323 my $log_file = test_get_logfile(); 324 325 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 326 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 327 328 my ($config_user, $config_group) = config_get_identity(); 329 330 my $anon_dir = File::Spec->rel2abs($tmpdir); 331 my $uid = 500; 332 my $gid = 500; 333 334 # Make sure that, if we're running as root, that the home directory has 335 # permissions/privs set for the account we create 336 if ($< == 0) { 337 unless (chmod(0755, $anon_dir)) { 338 die("Can't set perms on $anon_dir to 0755: $!"); 339 } 340 341 unless (chown($uid, $gid, $anon_dir)) { 342 die("Can't set owner of $anon_dir to $uid/$gid: $!"); 343 } 344 } 345 346 auth_user_write($auth_user_file, $config_user, 'foo', $uid, $gid, 347 '/tmp', '/bin/bash'); 348 auth_group_write($auth_group_file, $config_group, $gid, $config_user); 349 350 my $config = { 351 PidFile => $pid_file, 352 ScoreboardFile => $scoreboard_file, 353 SystemLog => $log_file, 354 TraceLog => $log_file, 355 Trace => 'DEFAULT:10 privs:10', 356 357 AuthUserFile => $auth_user_file, 358 AuthGroupFile => $auth_group_file, 359 360 IfModules => { 361 'mod_delay.c' => { 362 DelayEngine => 'off', 363 }, 364 }, 365 366 Anonymous => { 367 $anon_dir => { 368 User => $config_user, 369 Group => $config_group, 370 UserAlias => "anonymous $config_user", 371 RequireValidShell => 'off', 372 }, 373 }, 374 }; 375 376 my ($port, $user, $group) = config_write($config_file, $config); 377 378 # Open pipes, for use between the parent and child processes. Specifically, 379 # the child will indicate when it's done with its test by writing a message 380 # to the parent. 381 my ($rfh, $wfh); 382 unless (pipe($rfh, $wfh)) { 383 die("Can't open pipe: $!"); 384 } 385 386 my $ex; 387 388 # Fork child 389 $self->handle_sigchld(); 390 defined(my $pid = fork()) or die("Can't fork: $!"); 391 if ($pid) { 392 eval { 393 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 394 395 # In parent process, login anonymously to server using a plaintext 396 # password which SHOULD work. 397 my ($resp_code, $resp_msg) = $client->login($config_user, 'ftp@nospam.org'); 398 399 my $expected; 400 401 $expected = 230; 402 $self->assert($expected == $resp_code, 403 test_msg("Expected $expected, got $resp_code")); 404 405 $expected = 'Anonymous access granted, restrictions apply'; 406 $self->assert($expected eq $resp_msg, 407 test_msg("Expected '$expected', got '$resp_msg'")); 408 409 $client->quit(); 410 }; 411 412 if ($@) { 413 $ex = $@; 414 } 415 416 $wfh->print("done\n"); 417 $wfh->flush(); 418 419 } else { 420 eval { server_wait($config_file, $rfh) }; 421 if ($@) { 422 warn($@); 423 exit 1; 424 } 425 426 exit 0; 427 } 428 429 # Stop server 430 server_stop($pid_file); 431 432 $self->assert_child_ok($pid); 433 434 if ($ex) { 435 test_append_logfile($log_file, $ex); 436 unlink($log_file); 437 438 die($ex); 439 } 440 441 unlink($log_file); 442} 443 444sub login_anonymous_with_delay_ok { 445 my $self = shift; 446 my $tmpdir = $self->{tmpdir}; 447 448 my $config_file = "$tmpdir/login.conf"; 449 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 450 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 451 452 my $log_file = test_get_logfile(); 453 454 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 455 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 456 457 my ($config_user, $config_group) = config_get_identity(); 458 459 my $anon_dir = File::Spec->rel2abs($tmpdir); 460 my $uid = 500; 461 my $gid = 500; 462 463 # Make sure that, if we're running as root, that the home directory has 464 # permissions/privs set for the account we create 465 if ($< == 0) { 466 unless (chmod(0755, $anon_dir)) { 467 die("Can't set perms on $anon_dir to 0755: $!"); 468 } 469 470 unless (chown($uid, $gid, $anon_dir)) { 471 die("Can't set owner of $anon_dir to $uid/$gid: $!"); 472 } 473 } 474 475 auth_user_write($auth_user_file, $config_user, 'foo', $uid, $gid, 476 '/tmp', '/bin/bash'); 477 auth_group_write($auth_group_file, $config_group, $gid, $config_user); 478 479 my $delay_tab = File::Spec->rel2abs("$tmpdir/delay.tab"); 480 481 my $config = { 482 PidFile => $pid_file, 483 ScoreboardFile => $scoreboard_file, 484 SystemLog => $log_file, 485 TraceLog => $log_file, 486 Trace => 'DEFAULT:10 privs:10', 487 488 AuthUserFile => $auth_user_file, 489 AuthGroupFile => $auth_group_file, 490 491 IfModules => { 492 'mod_delay.c' => { 493 DelayTable => $delay_tab, 494 }, 495 }, 496 497 Anonymous => { 498 $anon_dir => { 499 User => $config_user, 500 Group => $config_group, 501 UserAlias => "anonymous $config_user", 502 RequireValidShell => 'off', 503 }, 504 }, 505 }; 506 507 my ($port, $user, $group) = config_write($config_file, $config); 508 509 # Open pipes, for use between the parent and child processes. Specifically, 510 # the child will indicate when it's done with its test by writing a message 511 # to the parent. 512 my ($rfh, $wfh); 513 unless (pipe($rfh, $wfh)) { 514 die("Can't open pipe: $!"); 515 } 516 517 my $ex; 518 519 # Fork child 520 $self->handle_sigchld(); 521 defined(my $pid = fork()) or die("Can't fork: $!"); 522 if ($pid) { 523 eval { 524 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 525 526 # In parent process, login anonymously to server using a plaintext 527 # password which SHOULD work. 528 my ($resp_code, $resp_msg) = $client->login($config_user, 'ftp@nospam.org'); 529 530 my $expected; 531 532 $expected = 230; 533 $self->assert($expected == $resp_code, 534 test_msg("Expected $expected, got $resp_code")); 535 536 $expected = 'Anonymous access granted, restrictions apply'; 537 $self->assert($expected eq $resp_msg, 538 test_msg("Expected '$expected', got '$resp_msg'")); 539 540 $client->quit(); 541 }; 542 543 if ($@) { 544 $ex = $@; 545 } 546 547 $wfh->print("done\n"); 548 $wfh->flush(); 549 550 } else { 551 eval { server_wait($config_file, $rfh) }; 552 if ($@) { 553 warn($@); 554 exit 1; 555 } 556 557 exit 0; 558 } 559 560 # Stop server 561 server_stop($pid_file); 562 563 $self->assert_child_ok($pid); 564 565 if ($ex) { 566 test_append_logfile($log_file, $ex); 567 unlink($log_file); 568 569 die($ex); 570 } 571 572 unlink($log_file); 573} 574 575sub login_anonymous_user_alias_ok { 576 my $self = shift; 577 my $tmpdir = $self->{tmpdir}; 578 579 my $config_file = "$tmpdir/login.conf"; 580 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 581 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 582 583 my $log_file = test_get_logfile(); 584 585 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 586 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 587 588 my ($config_user, $config_group) = config_get_identity(); 589 590 my $anon_dir = File::Spec->rel2abs($tmpdir); 591 my $uid = 500; 592 my $gid = 500; 593 594 # Make sure that, if we're running as root, that the home directory has 595 # permissions/privs set for the account we create 596 if ($< == 0) { 597 unless (chmod(0755, $anon_dir)) { 598 die("Can't set perms on $anon_dir to 0755: $!"); 599 } 600 601 unless (chown($uid, $gid, $anon_dir)) { 602 die("Can't set owner of $anon_dir to $uid/$gid: $!"); 603 } 604 } 605 606 auth_user_write($auth_user_file, $config_user, 'foo', $uid, $gid, 607 '/tmp', '/bin/bash'); 608 auth_group_write($auth_group_file, $config_group, $gid, $config_user); 609 610 my $config = { 611 PidFile => $pid_file, 612 ScoreboardFile => $scoreboard_file, 613 SystemLog => $log_file, 614 TraceLog => $log_file, 615 Trace => 'DEFAULT:10 privs:10', 616 617 AuthUserFile => $auth_user_file, 618 AuthGroupFile => $auth_group_file, 619 620 IfModules => { 621 'mod_delay.c' => { 622 DelayEngine => 'off', 623 }, 624 }, 625 626 Anonymous => { 627 $anon_dir => { 628 User => $config_user, 629 Group => $config_group, 630 UserAlias => "anonymous $config_user", 631 RequireValidShell => 'off', 632 }, 633 }, 634 }; 635 636 my ($port, $user, $group) = config_write($config_file, $config); 637 638 # Open pipes, for use between the parent and child processes. Specifically, 639 # the child will indicate when it's done with its test by writing a message 640 # to the parent. 641 my ($rfh, $wfh); 642 unless (pipe($rfh, $wfh)) { 643 die("Can't open pipe: $!"); 644 } 645 646 my $ex; 647 648 # Fork child 649 $self->handle_sigchld(); 650 defined(my $pid = fork()) or die("Can't fork: $!"); 651 if ($pid) { 652 eval { 653 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 654 655 # In parent process, login anonymously to server using a plaintext 656 # password which SHOULD work. 657 my ($resp_code, $resp_msg) = $client->login('anonymous', 'ftp@nospam.org'); 658 659 my $expected; 660 661 $expected = 230; 662 $self->assert($expected == $resp_code, 663 test_msg("Expected $expected, got $resp_code")); 664 665 $expected = 'Anonymous access granted, restrictions apply'; 666 $self->assert($expected eq $resp_msg, 667 test_msg("Expected '$expected', got '$resp_msg'")); 668 669 $client->quit(); 670 }; 671 672 if ($@) { 673 $ex = $@; 674 } 675 676 $wfh->print("done\n"); 677 $wfh->flush(); 678 679 } else { 680 eval { server_wait($config_file, $rfh) }; 681 if ($@) { 682 warn($@); 683 exit 1; 684 } 685 686 exit 0; 687 } 688 689 # Stop server 690 server_stop($pid_file); 691 692 $self->assert_child_ok($pid); 693 694 if ($ex) { 695 test_append_logfile($log_file, $ex); 696 unlink($log_file); 697 698 die($ex); 699 } 700 701 unlink($log_file); 702} 703 704sub login_anonymous_fails_bad_perms { 705 my $self = shift; 706 my $tmpdir = $self->{tmpdir}; 707 708 my $config_file = "$tmpdir/login.conf"; 709 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 710 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 711 712 my $log_file = test_get_logfile(); 713 714 my $anon_dir = File::Spec->rel2abs($tmpdir); 715 716 my ($user, $group) = config_get_identity(); 717 718 my $config = { 719 PidFile => $pid_file, 720 ScoreboardFile => $scoreboard_file, 721 SystemLog => $log_file, 722 723 IfModules => { 724 'mod_delay.c' => { 725 DelayEngine => 'off', 726 }, 727 }, 728 729 Anonymous => { 730 $anon_dir => { 731 User => $user, 732 Group => $group, 733 UserAlias => "anonymous $user", 734 RequireValidShell => 'off', 735 }, 736 }, 737 }; 738 739 my ($port, $config_user, $config_group) = config_write($config_file, $config); 740 741 # Open pipes, for use between the parent and child processes. Specifically, 742 # the child will indicate when it's done with its test by writing a message 743 # to the parent. 744 my ($rfh, $wfh); 745 unless (pipe($rfh, $wfh)) { 746 die("Can't open pipe: $!"); 747 } 748 749 my $ex; 750 751 # Fork child 752 $self->handle_sigchld(); 753 defined(my $pid = fork()) or die("Can't fork: $!"); 754 if ($pid) { 755 eval { 756 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 757 758 my $perms = (stat($anon_dir))[2]; 759 chmod(0660, $anon_dir); 760 761 eval { $client->login('anonymous', 'ftp@nospam.org') }; 762 unless ($@) { 763 die("Unexpectedly logged in anonymously"); 764 } 765 766 chmod($perms, $anon_dir); 767 }; 768 769 if ($@) { 770 $ex = $@; 771 } 772 773 $wfh->print("done\n"); 774 $wfh->flush(); 775 776 } else { 777 eval { server_wait($config_file, $rfh) }; 778 if ($@) { 779 warn($@); 780 exit 1; 781 } 782 783 exit 0; 784 } 785 786 # Stop server 787 server_stop($pid_file); 788 789 $self->assert_child_ok($pid); 790 791 if ($ex) { 792 test_append_logfile($log_file, $ex); 793 unlink($log_file); 794 795 die($ex); 796 } 797 798 unlink($log_file); 799} 800 801sub login_anonymous_fails_empty_password_bug4139 { 802 my $self = shift; 803 my $tmpdir = $self->{tmpdir}; 804 805 my $config_file = "$tmpdir/login.conf"; 806 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 807 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 808 809 my $log_file = test_get_logfile(); 810 811 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 812 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 813 814 my ($config_user, $config_group) = config_get_identity(); 815 816 my $anon_dir = File::Spec->rel2abs($tmpdir); 817 my $uid = 500; 818 my $gid = 500; 819 820 # Make sure that, if we're running as root, that the home directory has 821 # permissions/privs set for the account we create 822 if ($< == 0) { 823 unless (chmod(0755, $anon_dir)) { 824 die("Can't set perms on $anon_dir to 0755: $!"); 825 } 826 827 unless (chown($uid, $gid, $anon_dir)) { 828 die("Can't set owner of $anon_dir to $uid/$gid: $!"); 829 } 830 } 831 832 auth_user_write($auth_user_file, $config_user, 'foo', $uid, $gid, 833 '/tmp', '/bin/bash'); 834 auth_group_write($auth_group_file, $config_group, $gid, $config_user); 835 836 my $config = { 837 PidFile => $pid_file, 838 ScoreboardFile => $scoreboard_file, 839 SystemLog => $log_file, 840 TraceLog => $log_file, 841 Trace => 'DEFAULT:10 privs:10', 842 843 AuthUserFile => $auth_user_file, 844 AuthGroupFile => $auth_group_file, 845 846 IfModules => { 847 'mod_delay.c' => { 848 DelayEngine => 'off', 849 }, 850 }, 851 852 Anonymous => { 853 $anon_dir => { 854 User => $config_user, 855 Group => $config_group, 856 UserAlias => "anonymous $config_user", 857 RequireValidShell => 'off', 858 AllowEmptyPasswords => 'off', 859 }, 860 }, 861 }; 862 863 my ($port, $user, $group) = config_write($config_file, $config); 864 865 # Open pipes, for use between the parent and child processes. Specifically, 866 # the child will indicate when it's done with its test by writing a message 867 # to the parent. 868 my ($rfh, $wfh); 869 unless (pipe($rfh, $wfh)) { 870 die("Can't open pipe: $!"); 871 } 872 873 my $ex; 874 875 # Fork child 876 $self->handle_sigchld(); 877 defined(my $pid = fork()) or die("Can't fork: $!"); 878 if ($pid) { 879 eval { 880 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 881 eval { $client->login($config_user, '') }; 882 unless ($@) { 883 die("Anonymous login succeeded unexpectedly"); 884 } 885 886 my $resp_code = $client->response_code(); 887 my $resp_msg = $client->response_msg(); 888 889 my $expected; 890 891 $expected = 501; 892 $self->assert($expected == $resp_code, 893 test_msg("Expected response code $expected, got $resp_code")); 894 895 $expected = 'Login incorrect.'; 896 $self->assert($expected eq $resp_msg, 897 test_msg("Expected response message '$expected', got '$resp_msg'")); 898 899 $client->quit(); 900 }; 901 902 if ($@) { 903 $ex = $@; 904 } 905 906 $wfh->print("done\n"); 907 $wfh->flush(); 908 909 } else { 910 eval { server_wait($config_file, $rfh) }; 911 if ($@) { 912 warn($@); 913 exit 1; 914 } 915 916 exit 0; 917 } 918 919 # Stop server 920 server_stop($pid_file); 921 922 $self->assert_child_ok($pid); 923 924 if ($ex) { 925 test_append_logfile($log_file, $ex); 926 unlink($log_file); 927 928 die($ex); 929 } 930 931 unlink($log_file); 932} 933 934sub login_anonymous_symlink_dir_ok { 935 my $self = shift; 936 my $tmpdir = $self->{tmpdir}; 937 938 my $config_file = "$tmpdir/login.conf"; 939 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 940 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 941 942 my $log_file = test_get_logfile(); 943 944 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 945 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 946 947 my ($config_user, $config_group) = config_get_identity(); 948 949 my $anon_dir = File::Spec->rel2abs("$tmpdir/users/anonymous"); 950 my $uid = 500; 951 my $gid = 500; 952 953 my $intermed_dir = File::Spec->rel2abs("$tmpdir/users"); 954 mkpath($intermed_dir); 955 956 my $symlink_dst = File::Spec->rel2abs("$tmpdir/public_ftp"); 957 mkpath($symlink_dst); 958 959 my $cwd = getcwd(); 960 961 unless (chdir($intermed_dir)) { 962 die("Can't chdir to $intermed_dir: $!"); 963 } 964 965 unless (symlink("../public_ftp", "./anonymous")) { 966 die("Can't symlink '../public_ftp' to './anonymous': $!"); 967 } 968 969 unless (chdir($cwd)) { 970 die("Can't chdir to $cwd: $!"); 971 } 972 973 # Make sure that, if we're running as root, that the home directory has 974 # permissions/privs set for the account we create 975 if ($< == 0) { 976 unless (chmod(0755, $symlink_dst)) { 977 die("Can't set perms on $symlink_dst to 0755: $!"); 978 } 979 980 unless (chown($uid, $gid, $symlink_dst)) { 981 die("Can't set owner of $symlink_dst to $uid/$gid: $!"); 982 } 983 } 984 985 auth_user_write($auth_user_file, $config_user, 'foo', $uid, $gid, 986 '/tmp', '/bin/bash'); 987 auth_group_write($auth_group_file, $config_group, $gid, $config_user); 988 989 my $config = { 990 PidFile => $pid_file, 991 ScoreboardFile => $scoreboard_file, 992 SystemLog => $log_file, 993 TraceLog => $log_file, 994 Trace => 'DEFAULT:10 privs:10', 995 996 AuthUserFile => $auth_user_file, 997 AuthGroupFile => $auth_group_file, 998 999 IfModules => { 1000 'mod_delay.c' => { 1001 DelayEngine => 'off', 1002 }, 1003 }, 1004 1005 Anonymous => { 1006 $anon_dir => { 1007 User => $config_user, 1008 Group => $config_group, 1009 UserAlias => "anonymous $config_user", 1010 RequireValidShell => 'off', 1011 }, 1012 }, 1013 }; 1014 1015 my ($port, $user, $group) = config_write($config_file, $config); 1016 1017 # Open pipes, for use between the parent and child processes. Specifically, 1018 # the child will indicate when it's done with its test by writing a message 1019 # to the parent. 1020 my ($rfh, $wfh); 1021 unless (pipe($rfh, $wfh)) { 1022 die("Can't open pipe: $!"); 1023 } 1024 1025 my $ex; 1026 1027 # Fork child 1028 $self->handle_sigchld(); 1029 defined(my $pid = fork()) or die("Can't fork: $!"); 1030 if ($pid) { 1031 eval { 1032 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1033 1034 # In parent process, login anonymously to server using a plaintext 1035 # password which SHOULD work. 1036 my ($resp_code, $resp_msg) = $client->login($config_user, 'ftp@nospam.org'); 1037 1038 my $expected; 1039 1040 $expected = 230; 1041 $self->assert($expected == $resp_code, 1042 test_msg("Expected $expected, got $resp_code")); 1043 1044 $expected = 'Anonymous access granted, restrictions apply'; 1045 $self->assert($expected eq $resp_msg, 1046 test_msg("Expected '$expected', got '$resp_msg'")); 1047 1048 $client->quit(); 1049 }; 1050 1051 if ($@) { 1052 $ex = $@; 1053 } 1054 1055 $wfh->print("done\n"); 1056 $wfh->flush(); 1057 1058 } else { 1059 eval { server_wait($config_file, $rfh) }; 1060 if ($@) { 1061 warn($@); 1062 exit 1; 1063 } 1064 1065 exit 0; 1066 } 1067 1068 # Stop server 1069 server_stop($pid_file); 1070 1071 $self->assert_child_ok($pid); 1072 1073 if ($ex) { 1074 test_append_logfile($log_file, $ex); 1075 unlink($log_file); 1076 1077 die($ex); 1078 } 1079 1080 unlink($log_file); 1081} 1082 1083sub login_anonymous_allowchrootsymlinks_bug3852 { 1084 my $self = shift; 1085 my $tmpdir = $self->{tmpdir}; 1086 1087 my $config_file = "$tmpdir/login.conf"; 1088 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 1089 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 1090 1091 my $log_file = test_get_logfile(); 1092 1093 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 1094 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 1095 1096 my ($config_user, $config_group) = config_get_identity(); 1097 1098 my $anon_dir = File::Spec->rel2abs("$tmpdir/users/anonymous"); 1099 my $uid = 500; 1100 my $gid = 500; 1101 1102 my $intermed_dir = File::Spec->rel2abs("$tmpdir/users"); 1103 mkpath($intermed_dir); 1104 1105 my $symlink_dst = File::Spec->rel2abs("$tmpdir/public_ftp"); 1106 mkpath($symlink_dst); 1107 1108 my $cwd = getcwd(); 1109 1110 unless (chdir($intermed_dir)) { 1111 die("Can't chdir to $intermed_dir: $!"); 1112 } 1113 1114 unless (symlink("../public_ftp", "./anonymous")) { 1115 die("Can't symlink '../public_ftp' to './anonymous': $!"); 1116 } 1117 1118 unless (chdir($cwd)) { 1119 die("Can't chdir to $cwd: $!"); 1120 } 1121 1122 # Make sure that, if we're running as root, that the home directory has 1123 # permissions/privs set for the account we create 1124 if ($< == 0) { 1125 unless (chmod(0755, $symlink_dst)) { 1126 die("Can't set perms on $symlink_dst to 0755: $!"); 1127 } 1128 1129 unless (chown($uid, $gid, $symlink_dst)) { 1130 die("Can't set owner of $symlink_dst to $uid/$gid: $!"); 1131 } 1132 } 1133 1134 auth_user_write($auth_user_file, $config_user, 'foo', $uid, $gid, 1135 '/tmp', '/bin/bash'); 1136 auth_group_write($auth_group_file, $config_group, $gid, $config_user); 1137 1138 my $config = { 1139 PidFile => $pid_file, 1140 ScoreboardFile => $scoreboard_file, 1141 SystemLog => $log_file, 1142 TraceLog => $log_file, 1143 Trace => 'DEFAULT:10', 1144 1145 AuthUserFile => $auth_user_file, 1146 AuthGroupFile => $auth_group_file, 1147 1148 AllowChrootSymlinks => 'off', 1149 1150 IfModules => { 1151 'mod_delay.c' => { 1152 DelayEngine => 'off', 1153 }, 1154 }, 1155 1156 Anonymous => { 1157 $anon_dir => { 1158 User => $config_user, 1159 Group => $config_group, 1160 UserAlias => "anonymous $config_user", 1161 RequireValidShell => 'off', 1162 }, 1163 }, 1164 }; 1165 1166 my ($port, $user, $group) = config_write($config_file, $config); 1167 1168 # Open pipes, for use between the parent and child processes. Specifically, 1169 # the child will indicate when it's done with its test by writing a message 1170 # to the parent. 1171 my ($rfh, $wfh); 1172 unless (pipe($rfh, $wfh)) { 1173 die("Can't open pipe: $!"); 1174 } 1175 1176 my $ex; 1177 1178 # Fork child 1179 $self->handle_sigchld(); 1180 defined(my $pid = fork()) or die("Can't fork: $!"); 1181 if ($pid) { 1182 eval { 1183 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1184 eval { $client->login($config_user, 'ftp@nospam.org') }; 1185 unless ($@) { 1186 die("Anonymous login succeeded unexpectedly"); 1187 } 1188 1189 my $resp_code = $client->response_code(); 1190 my $resp_msg = $client->response_msg(); 1191 1192 my $expected; 1193 1194 $expected = 530; 1195 $self->assert($expected == $resp_code, 1196 test_msg("Expected response code $expected, got $resp_code")); 1197 1198 $expected = 'Login incorrect.'; 1199 $self->assert($expected eq $resp_msg, 1200 test_msg("Expected response message '$expected', got '$resp_msg'")); 1201 1202 $client->quit(); 1203 }; 1204 1205 if ($@) { 1206 $ex = $@; 1207 } 1208 1209 $wfh->print("done\n"); 1210 $wfh->flush(); 1211 1212 } else { 1213 eval { server_wait($config_file, $rfh) }; 1214 if ($@) { 1215 warn($@); 1216 exit 1; 1217 } 1218 1219 exit 0; 1220 } 1221 1222 # Stop server 1223 server_stop($pid_file); 1224 1225 $self->assert_child_ok($pid); 1226 1227 if ($ex) { 1228 test_append_logfile($log_file, $ex); 1229 unlink($log_file); 1230 1231 die($ex); 1232 } 1233 1234 unlink($log_file); 1235} 1236 1237sub login_multiple_attempts_per_conn { 1238 my $self = shift; 1239 my $tmpdir = $self->{tmpdir}; 1240 1241 my $config_file = "$tmpdir/login.conf"; 1242 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 1243 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 1244 1245 my $log_file = test_get_logfile(); 1246 1247 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 1248 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 1249 1250 my $test_file = File::Spec->rel2abs($config_file); 1251 1252 my $user = 'proftpd'; 1253 my $passwd = 'test'; 1254 my $group = 'ftpd'; 1255 my $home_dir = File::Spec->rel2abs($tmpdir); 1256 my $uid = 500; 1257 my $gid = 500; 1258 1259 # Make sure that, if we're running as root, that the home directory has 1260 # permissions/privs set for the account we create 1261 if ($< == 0) { 1262 unless (chmod(0755, $home_dir)) { 1263 die("Can't set perms on $home_dir to 0755: $!"); 1264 } 1265 1266 unless (chown($uid, $gid, $home_dir)) { 1267 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1268 } 1269 } 1270 1271 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1272 '/bin/bash'); 1273 auth_group_write($auth_group_file, $group, $gid, $user); 1274 1275 my $config = { 1276 PidFile => $pid_file, 1277 ScoreboardFile => $scoreboard_file, 1278 SystemLog => $log_file, 1279 1280 AuthUserFile => $auth_user_file, 1281 AuthGroupFile => $auth_group_file, 1282 1283 IfModules => { 1284 'mod_delay.c' => { 1285 DelayEngine => 'off', 1286 }, 1287 }, 1288 }; 1289 1290 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1291 1292 # Open pipes, for use between the parent and child processes. Specifically, 1293 # the child will indicate when it's done with its test by writing a message 1294 # to the parent. 1295 my ($rfh, $wfh); 1296 unless (pipe($rfh, $wfh)) { 1297 die("Can't open pipe: $!"); 1298 } 1299 1300 my $ex; 1301 1302 # Fork child 1303 $self->handle_sigchld(); 1304 defined(my $pid = fork()) or die("Can't fork: $!"); 1305 if ($pid) { 1306 eval { 1307 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1308 eval { $client->login($user, 'foo') }; 1309 unless ($@) { 1310 die("Login succeeded unexpectedly"); 1311 } 1312 1313 $client->login($user, $passwd); 1314 }; 1315 1316 if ($@) { 1317 $ex = $@; 1318 } 1319 1320 $wfh->print("done\n"); 1321 $wfh->flush(); 1322 1323 } else { 1324 eval { server_wait($config_file, $rfh) }; 1325 if ($@) { 1326 warn($@); 1327 exit 1; 1328 } 1329 1330 exit 0; 1331 } 1332 1333 # Stop server 1334 server_stop($pid_file); 1335 1336 $self->assert_child_ok($pid); 1337 1338 if ($ex) { 1339 test_append_logfile($log_file, $ex); 1340 unlink($log_file); 1341 1342 die($ex); 1343 } 1344 1345 unlink($log_file); 1346} 1347 1348sub login_regular_with_anon_defined_bug3307 { 1349 my $self = shift; 1350 my $tmpdir = $self->{tmpdir}; 1351 1352 my $config_file = "$tmpdir/login.conf"; 1353 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 1354 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 1355 1356 my $log_file = test_get_logfile(); 1357 1358 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 1359 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 1360 1361 my $test_file = File::Spec->rel2abs($config_file); 1362 1363 my $user = 'proftpd'; 1364 my $passwd = 'test'; 1365 my $home_dir = File::Spec->rel2abs($tmpdir); 1366 my $uid = 500; 1367 my $gid = 500; 1368 1369 # Make sure that, if we're running as root, that the home directory has 1370 # permissions/privs set for the account we create 1371 if ($< == 0) { 1372 unless (chmod(0755, $home_dir)) { 1373 die("Can't set perms on $home_dir to 0755: $!"); 1374 } 1375 1376 unless (chown($uid, $gid, $home_dir)) { 1377 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1378 } 1379 } 1380 1381 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1382 '/bin/bash'); 1383 auth_group_write($auth_group_file, 'ftpd', $gid, $user); 1384 1385 my ($config_user, $config_group) = config_get_identity(); 1386 1387 my $config = { 1388 PidFile => $pid_file, 1389 ScoreboardFile => $scoreboard_file, 1390 SystemLog => $log_file, 1391 1392 AuthUserFile => $auth_user_file, 1393 AuthGroupFile => $auth_group_file, 1394 1395 Anonymous => { 1396 $home_dir => { 1397 User => $config_user, 1398 Group => $config_group, 1399 RequireValidShell => 'off', 1400 UserAlias => "anonymous $config_user", 1401 }, 1402 }, 1403 1404 IfModules => { 1405 'mod_delay.c' => { 1406 DelayEngine => 'off', 1407 }, 1408 }, 1409 }; 1410 1411 my $port; 1412 ($port, $config_user, $config_group) = config_write($config_file, $config); 1413 1414 # Open pipes, for use between the parent and child processes. Specifically, 1415 # the child will indicate when it's done with its test by writing a message 1416 # to the parent. 1417 my ($rfh, $wfh); 1418 unless (pipe($rfh, $wfh)) { 1419 die("Can't open pipe: $!"); 1420 } 1421 1422 my $ex; 1423 1424 # Fork child 1425 $self->handle_sigchld(); 1426 defined(my $pid = fork()) or die("Can't fork: $!"); 1427 if ($pid) { 1428 eval { 1429 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1430 1431 my ($resp_code, $resp_msg) = $client->user($user); 1432 1433 my $expected; 1434 1435 $expected = 331; 1436 $self->assert($expected == $resp_code, 1437 test_msg("Expected $expected, got $resp_code")); 1438 1439 $expected = "Password required for $user"; 1440 $self->assert($expected eq $resp_msg, 1441 test_msg("Expected '$expected', got '$resp_msg'")); 1442 1443 $client->quit(); 1444 }; 1445 1446 if ($@) { 1447 $ex = $@; 1448 } 1449 1450 $wfh->print("done\n"); 1451 $wfh->flush(); 1452 1453 } else { 1454 eval { server_wait($config_file, $rfh) }; 1455 if ($@) { 1456 warn($@); 1457 exit 1; 1458 } 1459 1460 exit 0; 1461 } 1462 1463 # Stop server 1464 server_stop($pid_file); 1465 1466 $self->assert_child_ok($pid); 1467 1468 if ($ex) { 1469 test_append_logfile($log_file, $ex); 1470 unlink($log_file); 1471 1472 die($ex); 1473 } 1474 1475 unlink($log_file); 1476} 1477 1478sub login_fails_bad_sequence { 1479 my $self = shift; 1480 my $tmpdir = $self->{tmpdir}; 1481 1482 my $config_file = "$tmpdir/login.conf"; 1483 my $pid_file = File::Spec->rel2abs("$tmpdir/login.pid"); 1484 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/login.scoreboard"); 1485 1486 my $log_file = test_get_logfile(); 1487 1488 my $auth_user_file = File::Spec->rel2abs("$tmpdir/login.passwd"); 1489 my $auth_group_file = File::Spec->rel2abs("$tmpdir/login.group"); 1490 1491 my $user = 'proftpd'; 1492 my $passwd = 'test'; 1493 my $group = 'ftpd'; 1494 my $home_dir = File::Spec->rel2abs($tmpdir); 1495 my $uid = 500; 1496 my $gid = 500; 1497 1498 # Make sure that, if we're running as root, that the home directory has 1499 # permissions/privs set for the account we create 1500 if ($< == 0) { 1501 unless (chmod(0755, $home_dir)) { 1502 die("Can't set perms on $home_dir to 0755: $!"); 1503 } 1504 1505 unless (chown($uid, $gid, $home_dir)) { 1506 die("Can't set owner of $home_dir to $uid/$gid: $!"); 1507 } 1508 } 1509 1510 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 1511 '/bin/bash'); 1512 auth_group_write($auth_group_file, $group, $gid, $user); 1513 1514 my $config = { 1515 PidFile => $pid_file, 1516 ScoreboardFile => $scoreboard_file, 1517 SystemLog => $log_file, 1518 1519 AuthUserFile => $auth_user_file, 1520 AuthGroupFile => $auth_group_file, 1521 1522 IfModules => { 1523 'mod_delay.c' => { 1524 DelayEngine => 'off', 1525 }, 1526 }, 1527 }; 1528 1529 my ($port, $config_user, $config_group) = config_write($config_file, $config); 1530 1531 # Open pipes, for use between the parent and child processes. Specifically, 1532 # the child will indicate when it's done with its test by writing a message 1533 # to the parent. 1534 my ($rfh, $wfh); 1535 unless (pipe($rfh, $wfh)) { 1536 die("Can't open pipe: $!"); 1537 } 1538 1539 my $ex; 1540 1541 # Fork child 1542 $self->handle_sigchld(); 1543 defined(my $pid = fork()) or die("Can't fork: $!"); 1544 if ($pid) { 1545 eval { 1546 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1547 $client->user($user); 1548 1549 eval { $client->pwd() }; 1550 unless ($@) { 1551 die("PWD after USER succeeded unexpectedly"); 1552 } 1553 1554 my $resp_code = $client->response_code(); 1555 my $resp_msg = $client->response_msg(); 1556 1557 my $expected = 530; 1558 $self->assert($expected == $resp_code, 1559 test_msg("Expected response code $expected, got $resp_code")); 1560 1561 $expected = "Please login with USER and PASS"; 1562 $self->assert($expected eq $resp_msg, 1563 test_msg("Expected response message '$expected', got '$resp_msg'")); 1564 }; 1565 1566 if ($@) { 1567 $ex = $@; 1568 } 1569 1570 $wfh->print("done\n"); 1571 $wfh->flush(); 1572 1573 } else { 1574 eval { server_wait($config_file, $rfh) }; 1575 if ($@) { 1576 warn($@); 1577 exit 1; 1578 } 1579 1580 exit 0; 1581 } 1582 1583 # Stop server 1584 server_stop($pid_file); 1585 1586 $self->assert_child_ok($pid); 1587 1588 if ($ex) { 1589 test_append_logfile($log_file, $ex); 1590 unlink($log_file); 1591 1592 die($ex); 1593 } 1594 1595 unlink($log_file); 1596} 1597 1598sub login_reauthenticate_fails_bug3736 { 1599 my $self = shift; 1600 my $tmpdir = $self->{tmpdir}; 1601 my $setup = test_setup($tmpdir, 'login'); 1602 1603 my $config = { 1604 PidFile => $setup->{pid_file}, 1605 ScoreboardFile => $setup->{scoreboard_file}, 1606 SystemLog => $setup->{log_file}, 1607 1608 AuthUserFile => $setup->{auth_user_file}, 1609 AuthGroupFile => $setup->{auth_group_file}, 1610 1611 IfModules => { 1612 'mod_delay.c' => { 1613 DelayEngine => 'off', 1614 }, 1615 }, 1616 }; 1617 1618 my ($port, $config_user, $config_group) = config_write($setup->{config_file}, 1619 $config); 1620 1621 # Open pipes, for use between the parent and child processes. Specifically, 1622 # the child will indicate when it's done with its test by writing a message 1623 # to the parent. 1624 my ($rfh, $wfh); 1625 unless (pipe($rfh, $wfh)) { 1626 die("Can't open pipe: $!"); 1627 } 1628 1629 my $ex; 1630 1631 # Fork child 1632 $self->handle_sigchld(); 1633 defined(my $pid = fork()) or die("Can't fork: $!"); 1634 if ($pid) { 1635 eval { 1636 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1637 $client->login($setup->{user}, $setup->{passwd}); 1638 1639 my $other_user = 'foobar'; 1640 eval { $client->user($other_user) }; 1641 unless ($@) { 1642 die("Subsequent USER command succeeded unexpectedly"); 1643 } 1644 1645 my $resp_code = $client->response_code(); 1646 my $resp_msg = $client->response_msg(); 1647 1648 my $expected = 501; 1649 $self->assert($expected == $resp_code, 1650 test_msg("Expected response code $expected, got $resp_code")); 1651 1652 $expected = "Reauthentication not supported"; 1653 $self->assert($expected eq $resp_msg, 1654 test_msg("Expected response message '$expected', got '$resp_msg'")); 1655 }; 1656 1657 if ($@) { 1658 $ex = $@; 1659 } 1660 1661 $wfh->print("done\n"); 1662 $wfh->flush(); 1663 1664 } else { 1665 eval { server_wait($setup->{config_file}, $rfh) }; 1666 if ($@) { 1667 warn($@); 1668 exit 1; 1669 } 1670 1671 exit 0; 1672 } 1673 1674 # Stop server 1675 server_stop($setup->{pid_file}); 1676 $self->assert_child_ok($pid); 1677 1678 test_cleanup($setup->{log_file}, $ex); 1679} 1680 1681sub login_reauthenticate_ok_same_user_bug4217 { 1682 my $self = shift; 1683 my $tmpdir = $self->{tmpdir}; 1684 my $setup = test_setup($tmpdir, 'login'); 1685 1686 my $config = { 1687 PidFile => $setup->{pid_file}, 1688 ScoreboardFile => $setup->{scoreboard_file}, 1689 SystemLog => $setup->{log_file}, 1690 1691 AuthUserFile => $setup->{auth_user_file}, 1692 AuthGroupFile => $setup->{auth_group_file}, 1693 1694 IfModules => { 1695 'mod_delay.c' => { 1696 DelayEngine => 'off', 1697 }, 1698 }, 1699 }; 1700 1701 my ($port, $config_user, $config_group) = config_write($setup->{config_file}, 1702 $config); 1703 1704 # Open pipes, for use between the parent and child processes. Specifically, 1705 # the child will indicate when it's done with its test by writing a message 1706 # to the parent. 1707 my ($rfh, $wfh); 1708 unless (pipe($rfh, $wfh)) { 1709 die("Can't open pipe: $!"); 1710 } 1711 1712 my $ex; 1713 1714 # Fork child 1715 $self->handle_sigchld(); 1716 defined(my $pid = fork()) or die("Can't fork: $!"); 1717 if ($pid) { 1718 eval { 1719 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1720 $client->login($setup->{user}, $setup->{passwd}); 1721 1722 my ($resp_code, $resp_msg) = $client->user($setup->{user}); 1723 my $expected = 230; 1724 $self->assert($expected == $resp_code, 1725 test_msg("Expected response code $expected, got $resp_code")); 1726 1727 $expected = "User $setup->{user} logged in"; 1728 $self->assert($expected eq $resp_msg, 1729 test_msg("Expected response message '$expected', got '$resp_msg'")); 1730 }; 1731 1732 if ($@) { 1733 $ex = $@; 1734 } 1735 1736 $wfh->print("done\n"); 1737 $wfh->flush(); 1738 1739 } else { 1740 eval { server_wait($setup->{config_file}, $rfh) }; 1741 if ($@) { 1742 warn($@); 1743 exit 1; 1744 } 1745 1746 exit 0; 1747 } 1748 1749 # Stop server 1750 server_stop($setup->{pid_file}); 1751 $self->assert_child_ok($pid); 1752 1753 test_cleanup($setup->{log_file}, $ex); 1754} 1755 1756sub login_reauthenticate_fails_different_user_bug4217 { 1757 my $self = shift; 1758 my $tmpdir = $self->{tmpdir}; 1759 my $setup = test_setup($tmpdir, 'login'); 1760 1761 my $config = { 1762 PidFile => $setup->{pid_file}, 1763 ScoreboardFile => $setup->{scoreboard_file}, 1764 SystemLog => $setup->{log_file}, 1765 1766 AuthUserFile => $setup->{auth_user_file}, 1767 AuthGroupFile => $setup->{auth_group_file}, 1768 1769 IfModules => { 1770 'mod_delay.c' => { 1771 DelayEngine => 'off', 1772 }, 1773 }, 1774 }; 1775 1776 my ($port, $config_user, $config_group) = config_write($setup->{config_file}, 1777 $config); 1778 1779 # Open pipes, for use between the parent and child processes. Specifically, 1780 # the child will indicate when it's done with its test by writing a message 1781 # to the parent. 1782 my ($rfh, $wfh); 1783 unless (pipe($rfh, $wfh)) { 1784 die("Can't open pipe: $!"); 1785 } 1786 1787 my $ex; 1788 1789 # Fork child 1790 $self->handle_sigchld(); 1791 defined(my $pid = fork()) or die("Can't fork: $!"); 1792 if ($pid) { 1793 eval { 1794 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1795 $client->login($setup->{user}, $setup->{passwd}); 1796 1797 my $bad_user = "foobar"; 1798 eval { $client->user($bad_user) }; 1799 unless ($@) { 1800 die("Subsequent USER with different name succeeded unexpectedly"); 1801 } 1802 1803 my $resp_code = $client->response_code(); 1804 my $resp_msg = $client->response_msg(); 1805 1806 my $expected = 501; 1807 $self->assert($expected == $resp_code, 1808 test_msg("Expected response code $expected, got $resp_code")); 1809 1810 $expected = "Reauthentication not supported"; 1811 $self->assert($expected eq $resp_msg, 1812 test_msg("Expected response message '$expected', got '$resp_msg'")); 1813 }; 1814 1815 if ($@) { 1816 $ex = $@; 1817 } 1818 1819 $wfh->print("done\n"); 1820 $wfh->flush(); 1821 1822 } else { 1823 eval { server_wait($setup->{config_file}, $rfh) }; 1824 if ($@) { 1825 warn($@); 1826 exit 1; 1827 } 1828 1829 exit 0; 1830 } 1831 1832 # Stop server 1833 server_stop($setup->{pid_file}); 1834 $self->assert_child_ok($pid); 1835 1836 test_cleanup($setup->{log_file}, $ex); 1837} 1838 1839sub login_reauthenticate_fails_extra_pass_bug4217 { 1840 my $self = shift; 1841 my $tmpdir = $self->{tmpdir}; 1842 my $setup = test_setup($tmpdir, 'login'); 1843 1844 my $config = { 1845 PidFile => $setup->{pid_file}, 1846 ScoreboardFile => $setup->{scoreboard_file}, 1847 SystemLog => $setup->{log_file}, 1848 1849 AuthUserFile => $setup->{auth_user_file}, 1850 AuthGroupFile => $setup->{auth_group_file}, 1851 1852 IfModules => { 1853 'mod_delay.c' => { 1854 DelayEngine => 'off', 1855 }, 1856 }, 1857 }; 1858 1859 my ($port, $config_user, $config_group) = config_write($setup->{config_file}, 1860 $config); 1861 1862 # Open pipes, for use between the parent and child processes. Specifically, 1863 # the child will indicate when it's done with its test by writing a message 1864 # to the parent. 1865 my ($rfh, $wfh); 1866 unless (pipe($rfh, $wfh)) { 1867 die("Can't open pipe: $!"); 1868 } 1869 1870 my $ex; 1871 1872 # Fork child 1873 $self->handle_sigchld(); 1874 defined(my $pid = fork()) or die("Can't fork: $!"); 1875 if ($pid) { 1876 eval { 1877 my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); 1878 $client->login($setup->{user}, $setup->{passwd}); 1879 1880 # We can't use login() here, since that will properly handle the 230 1881 # response from the USER command. 1882 $client->user($setup->{user}); 1883 eval { $client->pass($setup->{passwd}) }; 1884 unless ($@) { 1885 die("Subsequent PASS succeeded unexpectedly"); 1886 } 1887 1888 my $resp_code = $client->response_code(); 1889 my $resp_msg = $client->response_msg(); 1890 1891 my $expected = 503; 1892 $self->assert($expected == $resp_code, 1893 test_msg("Expected response code $expected, got $resp_code")); 1894 1895 $expected = "You are already logged in"; 1896 $self->assert($expected eq $resp_msg, 1897 test_msg("Expected response message '$expected', got '$resp_msg'")); 1898 }; 1899 1900 if ($@) { 1901 $ex = $@; 1902 } 1903 1904 $wfh->print("done\n"); 1905 $wfh->flush(); 1906 1907 } else { 1908 eval { server_wait($setup->{config_file}, $rfh) }; 1909 if ($@) { 1910 warn($@); 1911 exit 1; 1912 } 1913 1914 exit 0; 1915 } 1916 1917 # Stop server 1918 server_stop($setup->{pid_file}); 1919 $self->assert_child_ok($pid); 1920 1921 test_cleanup($setup->{log_file}, $ex); 1922} 1923 19241; 1925