1package ProFTPD::Tests::Modules::mod_sftp::wrap2; 2 3use lib qw(t/lib); 4use base qw(ProFTPD::TestSuite::Child); 5use strict; 6 7use File::Copy; 8use File::Path qw(mkpath rmtree); 9use File::Spec; 10use IO::Handle; 11use IPC::Open3; 12use POSIX qw(:fcntl_h); 13use Socket; 14 15use ProFTPD::TestSuite::FTP; 16use ProFTPD::TestSuite::Utils qw(:auth :config :features :running :test :testsuite); 17 18$| = 1; 19 20my $order = 0; 21 22my $TESTS = { 23 sftp_wrap2_file_login => { 24 order => ++$order, 25 test_class => [qw(bug forking mod_wrap2_file sftp ssh2)], 26 }, 27 28 sftp_wrap2_sql_login => { 29 order => ++$order, 30 test_class => [qw(bug forking mod_sql_sqlite mod_wrap2_sql sftp ssh2)], 31 }, 32 33 sftp_wrap2_deny_msg_on_connect_bug3670 => { 34 order => ++$order, 35 test_class => [qw(bug forking mod_wrap2_file sftp ssh2)], 36 }, 37 38 sftp_wrap2_deny_msg_on_auth_bug3670 => { 39 order => ++$order, 40 test_class => [qw(bug forking mod_wrap2_file sftp ssh2)], 41 }, 42 43 sftp_wrap2_deny_msg_var_u => { 44 order => ++$order, 45 test_class => [qw(bug forking mod_wrap2_file sftp ssh2)], 46 }, 47 48}; 49 50sub new { 51 return shift()->SUPER::new(@_); 52} 53 54sub list_tests { 55 # Check for the required Perl modules: 56 # 57 # Net-SSH2 58 # Net-SSH2-SFTP 59 60 my $required = [qw( 61 Net::SSH2 62 Net::SSH2::SFTP 63 )]; 64 65 foreach my $req (@$required) { 66 eval "use $req"; 67 if ($@) { 68 print STDERR "\nWARNING:\n + Module '$req' not found, skipping all tests\n"; 69 70 if ($ENV{TEST_VERBOSE}) { 71 print STDERR "Unable to load $req: $@\n"; 72 } 73 74 return qw(testsuite_empty_test); 75 } 76 } 77 78 return testsuite_get_runnable_tests($TESTS); 79} 80 81sub set_up { 82 my $self = shift; 83 $self->SUPER::set_up(@_); 84 85 # Make sure that mod_sftp does not complain about permissions on the hostkey 86 # files. 87 88 my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); 89 my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); 90 91 unless (chmod(0400, $rsa_host_key, $dsa_host_key)) { 92 die("Can't set perms on $rsa_host_key, $dsa_host_key: $!"); 93 } 94} 95 96sub sftp_wrap2_file_login { 97 my $self = shift; 98 my $tmpdir = $self->{tmpdir}; 99 100 my $config_file = "$tmpdir/sftp.conf"; 101 my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid"); 102 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard"); 103 104 my $log_file = test_get_logfile(); 105 106 my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd"); 107 my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group"); 108 109 my $fh; 110 my $allow_file = File::Spec->rel2abs("$tmpdir/sftp.allow"); 111 if (open($fh, "> $allow_file")) { 112 print $fh "proftpd: ALL\n"; 113 114 unless (close($fh)) { 115 die("Can't write $allow_file: $!"); 116 } 117 118 } else { 119 die("Can't open $allow_file: $!"); 120 } 121 122 my $deny_file = File::Spec->rel2abs("$tmpdir/sftp.deny"); 123 if (open($fh, "> $deny_file")) { 124 print $fh "ALL: ALL\n"; 125 126 unless (close($fh)) { 127 die("Can't write $deny_file: $!"); 128 } 129 130 } else { 131 die("Can't open $deny_file: $!"); 132 } 133 134 my $user = 'proftpd'; 135 my $passwd = 'test'; 136 my $group = 'ftpd'; 137 my $home_dir = File::Spec->rel2abs($tmpdir); 138 my $uid = 500; 139 my $gid = 500; 140 141 # Make sure that, if we're running as root, that the home directory has 142 # permissions/privs set for the account we create 143 if ($< == 0) { 144 unless (chmod(0755, $home_dir)) { 145 die("Can't set perms on $home_dir to 0755: $!"); 146 } 147 148 unless (chown($uid, $gid, $home_dir)) { 149 die("Can't set owner of $home_dir to $uid/$gid: $!"); 150 } 151 } 152 153 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 154 '/bin/bash'); 155 auth_group_write($auth_group_file, $group, $gid, $user); 156 157 my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); 158 my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); 159 160 my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key'); 161 my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub'); 162 163 my $config = { 164 PidFile => $pid_file, 165 ScoreboardFile => $scoreboard_file, 166 SystemLog => $log_file, 167 TraceLog => $log_file, 168 Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20', 169 170 AuthUserFile => $auth_user_file, 171 AuthGroupFile => $auth_group_file, 172 173 IfModules => { 174 'mod_delay.c' => { 175 DelayEngine => 'off', 176 }, 177 178 'mod_sftp.c' => [ 179 "SFTPEngine on", 180 "SFTPLog $log_file", 181 "SFTPHostKey $rsa_host_key", 182 "SFTPHostKey $dsa_host_key", 183 ], 184 185 'mod_wrap2.c' => { 186 WrapEngine => 'on', 187 WrapLog => $log_file, 188 WrapTables => "file:$allow_file file:$deny_file", 189 WrapDenyMsg => "User '%u' denied by access rules", 190 WrapAllowMsg => "User '%u' allowed by access rules", 191 }, 192 }, 193 }; 194 195 my ($port, $config_user, $config_group) = config_write($config_file, $config); 196 197 # Open pipes, for use between the parent and child processes. Specifically, 198 # the child will indicate when it's done with its test by writing a message 199 # to the parent. 200 my ($rfh, $wfh); 201 unless (pipe($rfh, $wfh)) { 202 die("Can't open pipe: $!"); 203 } 204 205 require Net::SSH2; 206 207 my $ex; 208 209 # Fork child 210 $self->handle_sigchld(); 211 defined(my $pid = fork()) or die("Can't fork: $!"); 212 if ($pid) { 213 eval { 214 my $ssh2 = Net::SSH2->new(); 215 216 sleep(1); 217 218 unless ($ssh2->connect('127.0.0.1', $port)) { 219 my ($err_code, $err_name, $err_str) = $ssh2->error(); 220 die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str"); 221 } 222 223 if ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) { 224 die("Publickey auth succeeded unexpectedly"); 225 } 226 227 unless ($ssh2->auth_password($user, $passwd)) { 228 my ($err_code, $err_name, $err_str) = $ssh2->error(); 229 die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str"); 230 } 231 232 my $sftp = $ssh2->sftp(); 233 unless ($sftp) { 234 my ($err_code, $err_name, $err_str) = $ssh2->error(); 235 die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str"); 236 } 237 238 $sftp = undef; 239 $ssh2->disconnect(); 240 }; 241 242 if ($@) { 243 $ex = $@; 244 } 245 246 $wfh->print("done\n"); 247 $wfh->flush(); 248 249 } else { 250 eval { server_wait($config_file, $rfh) }; 251 if ($@) { 252 warn($@); 253 exit 1; 254 } 255 256 exit 0; 257 } 258 259 # Stop server 260 server_stop($pid_file); 261 262 $self->assert_child_ok($pid); 263 264 if ($ex) { 265 test_append_logfile($log_file, $ex); 266 unlink($log_file); 267 268 die($ex); 269 } 270 271 unlink($log_file); 272} 273 274sub sftp_wrap2_sql_login { 275 my $self = shift; 276 my $tmpdir = $self->{tmpdir}; 277 278 my $config_file = "$tmpdir/sftp.conf"; 279 my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid"); 280 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard"); 281 282 my $log_file = test_get_logfile(); 283 284 my $auth_user_file = File::Spec->rel2abs("$tmpdir/wrap2.passwd"); 285 my $auth_group_file = File::Spec->rel2abs("$tmpdir/wrap2.group"); 286 287 my $user = 'proftpd'; 288 my $passwd = 'test'; 289 my $group = 'ftpd'; 290 my $home_dir = File::Spec->rel2abs($tmpdir); 291 my $uid = 500; 292 my $gid = 500; 293 294 # Make sure that, if we're running as root, that the home directory has 295 # permissions/privs set for the account we create 296 if ($< == 0) { 297 unless (chmod(0755, $home_dir)) { 298 die("Can't set perms on $home_dir to 0755: $!"); 299 } 300 301 unless (chown($uid, $gid, $home_dir)) { 302 die("Can't set owner of $home_dir to $uid/$gid: $!"); 303 } 304 } 305 306 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 307 '/bin/bash'); 308 auth_group_write($auth_group_file, $group, $gid, $user); 309 310 my $db_file = File::Spec->rel2abs("$tmpdir/proftpd.db"); 311 312 # Build up sqlite3 command to create allow, deny tables and populate them 313 my $db_script = File::Spec->rel2abs("$tmpdir/proftpd.sql"); 314 315 my $fh; 316 if (open($fh, "> $db_script")) { 317 print $fh <<EOS; 318CREATE TABLE ftpallow ( 319 name TEXT, 320 allowed TEXT 321); 322INSERT INTO ftpallow (name, allowed) VALUES ('$user', 'ALL'); 323 324CREATE TABLE ftpdeny ( 325 name TEXT, 326 denied TEXT 327); 328 329EOS 330 331 unless (close($fh)) { 332 die("Can't write $db_script: $!"); 333 } 334 335 } else { 336 die("Can't open $db_script: $!"); 337 } 338 339 my $cmd = "sqlite3 $db_file < $db_script"; 340 341 if ($ENV{TEST_VERBOSE}) { 342 print STDERR "Executing sqlite3: $cmd\n"; 343 } 344 345 my @output = `$cmd`; 346 if (scalar(@output) > 0 && 347 $ENV{TEST_VERBOSE}) { 348 print STDERR "Output: ", join('', @output), "\n"; 349 } 350 351 unlink($db_script); 352 353 my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); 354 my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); 355 356 my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key'); 357 my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub'); 358 359 my $config = { 360 PidFile => $pid_file, 361 ScoreboardFile => $scoreboard_file, 362 SystemLog => $log_file, 363 TraceLog => $log_file, 364 Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20', 365 366 AuthUserFile => $auth_user_file, 367 AuthGroupFile => $auth_group_file, 368 369 IfModules => { 370 'mod_delay.c' => { 371 DelayEngine => 'off', 372 }, 373 374 'mod_sftp.c' => [ 375 "SFTPEngine on", 376 "SFTPLog $log_file", 377 "SFTPHostKey $rsa_host_key", 378 "SFTPHostKey $dsa_host_key", 379 ], 380 381 'mod_sql.c' => [ 382 'SQLAuthenticate off', 383 "SQLConnectInfo $db_file", 384 'SQLNamedQuery get-allowed-clients SELECT "allowed FROM ftpallow WHERE name = \'%u\'"', 385 'SQLNamedQuery get-denied-clients SELECT "denied FROM ftpdeny WHERE name = \'%u\'"', 386 "SQLLogFile $log_file", 387 ], 388 389 'mod_wrap2.c' => { 390 WrapEngine => 'on', 391 WrapLog => $log_file, 392 WrapTables => "sql:/get-allowed-clients sql:/get-denied-clients", 393 WrapDenyMsg => "User '%u' denied by access rules", 394 WrapAllowMsg => "User '%u' allowed by access rules", 395 }, 396 }, 397 }; 398 399 my ($port, $config_user, $config_group) = config_write($config_file, $config); 400 401 # Open pipes, for use between the parent and child processes. Specifically, 402 # the child will indicate when it's done with its test by writing a message 403 # to the parent. 404 my ($rfh, $wfh); 405 unless (pipe($rfh, $wfh)) { 406 die("Can't open pipe: $!"); 407 } 408 409 require Net::SSH2; 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 $ssh2 = Net::SSH2->new(); 419 420 sleep(1); 421 422 unless ($ssh2->connect('127.0.0.1', $port)) { 423 my ($err_code, $err_name, $err_str) = $ssh2->error(); 424 die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str"); 425 } 426 427 if ($ssh2->auth_publickey($user, $rsa_pub_key, $rsa_priv_key)) { 428 die("Publickey auth succeeded unexpectedly"); 429 } 430 431 unless ($ssh2->auth_password($user, $passwd)) { 432 my ($err_code, $err_name, $err_str) = $ssh2->error(); 433 die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str"); 434 } 435 436 my $sftp = $ssh2->sftp(); 437 unless ($sftp) { 438 my ($err_code, $err_name, $err_str) = $ssh2->error(); 439 die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str"); 440 } 441 442 $sftp = undef; 443 $ssh2->disconnect(); 444 }; 445 446 if ($@) { 447 $ex = $@; 448 } 449 450 $wfh->print("done\n"); 451 $wfh->flush(); 452 453 } else { 454 eval { server_wait($config_file, $rfh) }; 455 if ($@) { 456 warn($@); 457 exit 1; 458 } 459 460 exit 0; 461 } 462 463 # Stop server 464 server_stop($pid_file); 465 466 $self->assert_child_ok($pid); 467 468 if ($ex) { 469 test_append_logfile($log_file, $ex); 470 unlink($log_file); 471 472 die($ex); 473 } 474 475 unlink($log_file); 476} 477 478sub sftp_wrap2_deny_msg_on_connect_bug3670 { 479 my $self = shift; 480 my $tmpdir = $self->{tmpdir}; 481 482 my $config_file = "$tmpdir/sftp.conf"; 483 my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid"); 484 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard"); 485 486 my $log_file = test_get_logfile(); 487 488 my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd"); 489 my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group"); 490 491 my $fh; 492 my $allow_file = File::Spec->rel2abs("$tmpdir/sftp.allow"); 493 if (open($fh, "> $allow_file")) { 494 close($fh); 495 496 } else { 497 die("Can't open $allow_file: $!"); 498 } 499 500 my $deny_file = File::Spec->rel2abs("$tmpdir/sftp.deny"); 501 if (open($fh, "> $deny_file")) { 502 print $fh "ALL: ALL\n"; 503 504 unless (close($fh)) { 505 die("Can't write $deny_file: $!"); 506 } 507 508 } else { 509 die("Can't open $deny_file: $!"); 510 } 511 512 my $user = 'proftpd'; 513 my $passwd = 'test'; 514 my $group = 'ftpd'; 515 my $home_dir = File::Spec->rel2abs($tmpdir); 516 my $uid = 500; 517 my $gid = 500; 518 519 # Make sure that, if we're running as root, that the home directory has 520 # permissions/privs set for the account we create 521 if ($< == 0) { 522 unless (chmod(0755, $home_dir)) { 523 die("Can't set perms on $home_dir to 0755: $!"); 524 } 525 526 unless (chown($uid, $gid, $home_dir)) { 527 die("Can't set owner of $home_dir to $uid/$gid: $!"); 528 } 529 } 530 531 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 532 '/bin/bash'); 533 auth_group_write($auth_group_file, $group, $gid, $user); 534 535 my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); 536 my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); 537 538 my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key'); 539 my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub'); 540 541 my $deny_msg = '"SFTP denied by access rules"'; 542 543 # Note: This test only passes correctly IFF mod_sftp is loaded BEFORE 544 # mod_wrap2, not after. This means that mod_sftp needs to appear AFTER 545 # mod_wrap2 in the --with-modules list, or appear BEFORE mod_wrap2 in 546 # a list of LoadModule directives. 547 # 548 # mod_sftp's sess_init() callback is where the 'SSH2' protocol is set 549 # for the session. The event listener for mod_wrap2's "disconnect this 550 # client on connect because it isn't allowed by the access rules" has 551 # a condition that checks for whether the session is an SSH2 session or 552 # not (lest it trigger improperly for an FTP session). So if mod_wrap2's 553 # sess_init() callback triggers first, it will disconnect the session 554 # (and generate the event) before mod_sftp's sess_init() callback has had 555 # a chance to set the "SSH2" bit for the session, then mod_sftp won't 556 # properly send the WrapDenyMsg to the SSH2 client. 557 558 my $config = { 559 PidFile => $pid_file, 560 ScoreboardFile => $scoreboard_file, 561 SystemLog => $log_file, 562 TraceLog => $log_file, 563 Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20', 564 565 AuthUserFile => $auth_user_file, 566 AuthGroupFile => $auth_group_file, 567 568 IfModules => { 569 'mod_delay.c' => { 570 DelayEngine => 'off', 571 }, 572 573 'mod_sftp.c' => [ 574 "SFTPEngine on", 575 "SFTPLog $log_file", 576 "SFTPHostKey $rsa_host_key", 577 "SFTPHostKey $dsa_host_key", 578 "SFTPOptions PessimisticKexinit", 579 ], 580 581 'mod_wrap2.c' => { 582 WrapEngine => 'on', 583 WrapLog => $log_file, 584 WrapTables => "file:$allow_file file:$deny_file", 585 WrapDenyMsg => $deny_msg, 586 WrapOptions => 'CheckOnConnect', 587 }, 588 }, 589 }; 590 591 my ($port, $config_user, $config_group) = config_write($config_file, $config); 592 593 # Open pipes, for use between the parent and child processes. Specifically, 594 # the child will indicate when it's done with its test by writing a message 595 # to the parent. 596 my ($rfh, $wfh); 597 unless (pipe($rfh, $wfh)) { 598 die("Can't open pipe: $!"); 599 } 600 601 require Net::SSH2; 602 603 my $ex; 604 605 # Fork child 606 $self->handle_sigchld(); 607 defined(my $pid = fork()) or die("Can't fork: $!"); 608 if ($pid) { 609 eval { 610 sleep(1); 611 612 my $proto = getprotobyname('tcp'); 613 614 my $sock; 615 unless (socket($sock, PF_INET, SOCK_STREAM, $proto)) { 616 die("Can't create socket: $!"); 617 } 618 619 my $in_addr = inet_aton('127.0.0.1'); 620 my $addr = sockaddr_in($port, $in_addr); 621 622 unless (connect($sock, $addr)) { 623 die("Can't connect to 127.0.0.1:$port: $!"); 624 } 625 626 print $sock "SSH-2.0-MySFTPTestClient\r\n"; 627 628 my $buflen = 1024; 629 my $buf = ''; 630 my $tmp; 631 my $res; 632 633 while (my $res = read($sock, $tmp, $buflen)) { 634 $buf .= $tmp; 635 } 636 637 close($sock); 638 639 chomp($buf); 640 $buf =~ s/"//g; 641 642 $deny_msg =~ s/'//g; 643 $deny_msg =~ s/"//g; 644 645 $self->assert(qr/$deny_msg/, $buf, 646 test_msg("Expected response '$deny_msg', got '$buf'")); 647 }; 648 649 if ($@) { 650 $ex = $@; 651 } 652 653 $wfh->print("done\n"); 654 $wfh->flush(); 655 656 } else { 657 eval { server_wait($config_file, $rfh) }; 658 if ($@) { 659 warn($@); 660 exit 1; 661 } 662 663 exit 0; 664 } 665 666 # Stop server 667 server_stop($pid_file); 668 669 $self->assert_child_ok($pid); 670 671 if ($ex) { 672 test_append_logfile($log_file, $ex); 673 unlink($log_file); 674 675 die($ex); 676 } 677 678 unlink($log_file); 679} 680 681sub sftp_wrap2_deny_msg_on_auth_bug3670 { 682 my $self = shift; 683 my $tmpdir = $self->{tmpdir}; 684 685 my $config_file = "$tmpdir/sftp.conf"; 686 my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid"); 687 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard"); 688 689 my $log_file = test_get_logfile(); 690 691 my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd"); 692 my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group"); 693 694 my $fh; 695 my $allow_file = File::Spec->rel2abs("$tmpdir/sftp.allow"); 696 if (open($fh, "> $allow_file")) { 697 close($fh); 698 699 } else { 700 die("Can't open $allow_file: $!"); 701 } 702 703 my $deny_file = File::Spec->rel2abs("$tmpdir/sftp.deny"); 704 if (open($fh, "> $deny_file")) { 705 print $fh "ALL: ALL\n"; 706 707 unless (close($fh)) { 708 die("Can't write $deny_file: $!"); 709 } 710 711 } else { 712 die("Can't open $deny_file: $!"); 713 } 714 715 my $user = 'proftpd'; 716 my $passwd = 'test'; 717 my $group = 'ftpd'; 718 my $home_dir = File::Spec->rel2abs($tmpdir); 719 my $uid = 500; 720 my $gid = 500; 721 722 # Make sure that, if we're running as root, that the home directory has 723 # permissions/privs set for the account we create 724 if ($< == 0) { 725 unless (chmod(0755, $home_dir)) { 726 die("Can't set perms on $home_dir to 0755: $!"); 727 } 728 729 unless (chown($uid, $gid, $home_dir)) { 730 die("Can't set owner of $home_dir to $uid/$gid: $!"); 731 } 732 } 733 734 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 735 '/bin/bash'); 736 auth_group_write($auth_group_file, $group, $gid, $user); 737 738 my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); 739 my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); 740 741 my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key'); 742 my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub'); 743 744 my $deny_msg = '"SFTP denied by access rules"'; 745 746 my $config = { 747 PidFile => $pid_file, 748 ScoreboardFile => $scoreboard_file, 749 SystemLog => $log_file, 750 TraceLog => $log_file, 751 Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20', 752 753 AuthUserFile => $auth_user_file, 754 AuthGroupFile => $auth_group_file, 755 756 IfModules => { 757 'mod_delay.c' => { 758 DelayEngine => 'off', 759 }, 760 761 'mod_sftp.c' => [ 762 "SFTPEngine on", 763 "SFTPLog $log_file", 764 "SFTPHostKey $rsa_host_key", 765 "SFTPHostKey $dsa_host_key", 766 ], 767 768 'mod_wrap2.c' => { 769 WrapEngine => 'on', 770 WrapLog => $log_file, 771 WrapTables => "file:$allow_file file:$deny_file", 772 WrapDenyMsg => $deny_msg, 773 }, 774 }, 775 }; 776 777 my ($port, $config_user, $config_group) = config_write($config_file, $config); 778 779 # Open pipes, for use between the parent and child processes. Specifically, 780 # the child will indicate when it's done with its test by writing a message 781 # to the parent. 782 my ($rfh, $wfh); 783 unless (pipe($rfh, $wfh)) { 784 die("Can't open pipe: $!"); 785 } 786 787 require Net::SSH2; 788 789 my $ex; 790 791 # Fork child 792 $self->handle_sigchld(); 793 defined(my $pid = fork()) or die("Can't fork: $!"); 794 if ($pid) { 795 eval { 796 my $ssh2 = Net::SSH2->new(); 797 798 sleep(1); 799 800 unless ($ssh2->connect('127.0.0.1', $port)) { 801 my ($err_code, $err_name, $err_str) = $ssh2->error(); 802 die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str (see unit test notes)"); 803 } 804 805 if ($ssh2->auth_password($user, $passwd)) { 806 die("Password authentication succeeded unexpectedly"); 807 } 808 809 my ($err_code, $err_name, $err_str) = $ssh2->error(); 810 811 $ssh2->disconnect(); 812 813 # Unfortunately, the Net::SSH2::SFTP API doesn't provide the error 814 # text as sent by the SFTP server. 815 }; 816 817 if ($@) { 818 $ex = $@; 819 } 820 821 $wfh->print("done\n"); 822 $wfh->flush(); 823 824 } else { 825 eval { server_wait($config_file, $rfh) }; 826 if ($@) { 827 warn($@); 828 exit 1; 829 } 830 831 exit 0; 832 } 833 834 # Stop server 835 server_stop($pid_file); 836 837 $self->assert_child_ok($pid); 838 839 if ($ex) { 840 test_append_logfile($log_file, $ex); 841 unlink($log_file); 842 843 die($ex); 844 } 845 846 unlink($log_file); 847} 848 849sub sftp_wrap2_deny_msg_var_u { 850 my $self = shift; 851 my $tmpdir = $self->{tmpdir}; 852 853 my $config_file = "$tmpdir/sftp.conf"; 854 my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid"); 855 my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard"); 856 857 my $log_file = test_get_logfile(); 858 859 my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd"); 860 my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group"); 861 862 my $fh; 863 my $allow_file = File::Spec->rel2abs("$tmpdir/sftp.allow"); 864 if (open($fh, "> $allow_file")) { 865 close($fh); 866 867 } else { 868 die("Can't open $allow_file: $!"); 869 } 870 871 my $deny_file = File::Spec->rel2abs("$tmpdir/sftp.deny"); 872 if (open($fh, "> $deny_file")) { 873 print $fh "ALL: ALL\n"; 874 875 unless (close($fh)) { 876 die("Can't write $deny_file: $!"); 877 } 878 879 } else { 880 die("Can't open $deny_file: $!"); 881 } 882 883 my $user = 'proftpd'; 884 my $passwd = 'test'; 885 my $group = 'ftpd'; 886 my $home_dir = File::Spec->rel2abs($tmpdir); 887 my $uid = 500; 888 my $gid = 500; 889 890 # Make sure that, if we're running as root, that the home directory has 891 # permissions/privs set for the account we create 892 if ($< == 0) { 893 unless (chmod(0755, $home_dir)) { 894 die("Can't set perms on $home_dir to 0755: $!"); 895 } 896 897 unless (chown($uid, $gid, $home_dir)) { 898 die("Can't set owner of $home_dir to $uid/$gid: $!"); 899 } 900 } 901 902 auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, 903 '/bin/bash'); 904 auth_group_write($auth_group_file, $group, $gid, $user); 905 906 my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); 907 my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); 908 909 my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key'); 910 my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub'); 911 912 my $deny_msg = '"User %u denied by access rules"'; 913 914 my $config = { 915 PidFile => $pid_file, 916 ScoreboardFile => $scoreboard_file, 917 SystemLog => $log_file, 918 TraceLog => $log_file, 919 Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20', 920 921 AuthUserFile => $auth_user_file, 922 AuthGroupFile => $auth_group_file, 923 924 IfModules => { 925 'mod_delay.c' => { 926 DelayEngine => 'off', 927 }, 928 929 'mod_sftp.c' => [ 930 "SFTPEngine on", 931 "SFTPLog $log_file", 932 "SFTPHostKey $rsa_host_key", 933 "SFTPHostKey $dsa_host_key", 934 ], 935 936 'mod_wrap2.c' => { 937 WrapEngine => 'on', 938 WrapLog => $log_file, 939 WrapTables => "file:$allow_file file:$deny_file", 940 WrapDenyMsg => $deny_msg, 941 }, 942 }, 943 }; 944 945 my ($port, $config_user, $config_group) = config_write($config_file, $config); 946 947 # Open pipes, for use between the parent and child processes. Specifically, 948 # the child will indicate when it's done with its test by writing a message 949 # to the parent. 950 my ($rfh, $wfh); 951 unless (pipe($rfh, $wfh)) { 952 die("Can't open pipe: $!"); 953 } 954 955 require Net::SSH2; 956 957 my $ex; 958 959 # Fork child 960 $self->handle_sigchld(); 961 defined(my $pid = fork()) or die("Can't fork: $!"); 962 if ($pid) { 963 eval { 964 my $ssh2 = Net::SSH2->new(); 965 966 sleep(1); 967 968 unless ($ssh2->connect('127.0.0.1', $port)) { 969 my ($err_code, $err_name, $err_str) = $ssh2->error(); 970 die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str (see unit test notes)"); 971 } 972 973 if ($ssh2->auth_password($user, $passwd)) { 974 die("Password authentication succeeded unexpectedly"); 975 } 976 977 my ($err_code, $err_name, $err_str) = $ssh2->error(); 978 979 $ssh2->disconnect(); 980 981 # Unfortunately, the Net::SSH2::SFTP API doesn't provide the error 982 # text as sent by the SFTP server. 983 }; 984 985 if ($@) { 986 $ex = $@; 987 } 988 989 $wfh->print("done\n"); 990 $wfh->flush(); 991 992 } else { 993 eval { server_wait($config_file, $rfh) }; 994 if ($@) { 995 warn($@); 996 exit 1; 997 } 998 999 exit 0; 1000 } 1001 1002 # Stop server 1003 server_stop($pid_file); 1004 1005 $self->assert_child_ok($pid); 1006 1007 if ($ex) { 1008 test_append_logfile($log_file, $ex); 1009 unlink($log_file); 1010 1011 die($ex); 1012 } 1013 1014 unlink($log_file); 1015} 1016 10171; 1018