diff --git a/doc/modules/mod_auth.html b/doc/modules/mod_auth.html index 706cc69f0b..a80b297967 100644 --- a/doc/modules/mod_auth.html +++ b/doc/modules/mod_auth.html @@ -755,7 +755,7 @@
<IfModule mod_rewrite.c> RewriteEngine on - RewrlteLog /path/to/rewrite.log + RewriteLog /path/to/rewrite.log RewriteCondition %m REWRITE_HOME RewriteRule (.*) /my/new/prefix$1 diff --git a/tests/t/lib/ProFTPD/Tests/Modules/mod_sftp/rewrite.pm b/tests/t/lib/ProFTPD/Tests/Modules/mod_sftp/rewrite.pm index 030871703d..72507738c2 100644 --- a/tests/t/lib/ProFTPD/Tests/Modules/mod_sftp/rewrite.pm +++ b/tests/t/lib/ProFTPD/Tests/Modules/mod_sftp/rewrite.pm @@ -21,7 +21,17 @@ $| = 1; my $order = 0; my $TESTS = { - ssh2_rewrite_auth => { + ssh2_rewrite_auth_password => { + order => ++$order, + test_class => [qw(forking mod_rewrite ssh2)], + }, + + ssh2_rewrite_auth_publickey => { + order => ++$order, + test_class => [qw(forking mod_rewrite ssh2)], + }, + + ssh2_rewrite_auth_homedir => { order => ++$order, test_class => [qw(forking mod_rewrite ssh2)], }, @@ -186,54 +196,133 @@ sub set_up { } } -sub ssh2_rewrite_auth { +sub ssh2_rewrite_auth_password { my $self = shift; my $tmpdir = $self->{tmpdir}; + my $setup = test_setup($tmpdir, 'sftp'); - my $config_file = "$tmpdir/sftp.conf"; - my $pid_file = File::Spec->rel2abs("$tmpdir/sftp.pid"); - my $scoreboard_file = File::Spec->rel2abs("$tmpdir/sftp.scoreboard"); + my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); + my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); - my $log_file = test_get_logfile(); + my $config = { + PidFile => $setup->{pid_file}, + ScoreboardFile => $setup->{scoreboard_file}, + SystemLog => $setup->{log_file}, + TraceLog => $setup->{log_file}, + Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20', - my $auth_user_file = File::Spec->rel2abs("$tmpdir/sftp.passwd"); - my $auth_group_file = File::Spec->rel2abs("$tmpdir/sftp.group"); + AuthUserFile => $setup->{auth_user_file}, + AuthGroupFile => $setup->{auth_group_file}, - my $user = 'proftpd'; - my $passwd = 'test'; - my $group = 'ftpd'; - my $home_dir = File::Spec->rel2abs($tmpdir); - my $uid = 500; - my $gid = 500; + IfModules => { + 'mod_delay.c' => { + DelayEngine => 'off', + }, - # Make sure that, if we're running as root, that the home directory has - # permissions/privs set for the account we create - if ($< == 0) { - unless (chmod(0755, $home_dir)) { - die("Can't set perms on $home_dir to 0755: $!"); + 'mod_rewrite.c' => [ + 'RewriteEngine on', + "RewriteLog $setup->{log_file}", + + 'RewriteMap lowercase int:tolower', + 'RewriteCondition %m USER', + 'RewriteRule ^(.*)$ ${lowercase:$1}', + ], + + 'mod_sftp.c' => [ + "SFTPEngine on", + "SFTPLog $setup->{log_file}", + "SFTPHostKey $rsa_host_key", + "SFTPHostKey $dsa_host_key", + ], + }, + }; + + my ($port, $config_user, $config_group) = config_write($setup->{config_file}, + $config); + + # Open pipes, for use between the parent and child processes. Specifically, + # the child will indicate when it's done with its test by writing a message + # to the parent. + my ($rfh, $wfh); + unless (pipe($rfh, $wfh)) { + die("Can't open pipe: $!"); + } + + require Net::SSH2; + + my $ex; + + # Fork child + $self->handle_sigchld(); + defined(my $pid = fork()) or die("Can't fork: $!"); + if ($pid) { + eval { + my $ssh2 = Net::SSH2->new(); + + sleep(1); + + unless ($ssh2->connect('127.0.0.1', $port)) { + my ($err_code, $err_name, $err_str) = $ssh2->error(); + die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str"); + } + + unless ($ssh2->auth_password(uc($setup->{user}), $setup->{passwd})) { + my ($err_code, $err_name, $err_str) = $ssh2->error(); + die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str"); + } + + $ssh2->disconnect(); + }; + if ($@) { + $ex = $@; } - unless (chown($uid, $gid, $home_dir)) { - die("Can't set owner of $home_dir to $uid/$gid: $!"); + $wfh->print("done\n"); + $wfh->flush(); + + } else { + eval { server_wait($setup->{config_file}, $rfh) }; + if ($@) { + warn($@); + exit 1; } + + exit 0; } - auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, - '/bin/bash'); - auth_group_write($auth_group_file, $group, $gid, $user); + # Stop server + server_stop($setup->{pid_file}); + $self->assert_child_ok($pid); + + test_cleanup($setup->{log_file}, $ex); +} + +sub ssh2_rewrite_auth_publickey { + my $self = shift; + my $tmpdir = $self->{tmpdir}; + my $setup = test_setup($tmpdir, 'sftp'); my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); + my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key'); + my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub'); + my $rsa_rfc4716_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/authorized_rsa_keys2'); + + my $authorized_keys = File::Spec->rel2abs("$tmpdir/.authorized_keys"); + unless (copy($rsa_rfc4716_key, $authorized_keys)) { + die("Can't copy $rsa_rfc4716_key to $authorized_keys: $!"); + } + my $config = { - PidFile => $pid_file, - ScoreboardFile => $scoreboard_file, - SystemLog => $log_file, - TraceLog => $log_file, + PidFile => $setup->{pid_file}, + ScoreboardFile => $setup->{scoreboard_file}, + SystemLog => $setup->{log_file}, + TraceLog => $setup->{log_file}, Trace => 'DEFAULT:10 ssh2:20 sftp:20 scp:20', - AuthUserFile => $auth_user_file, - AuthGroupFile => $auth_group_file, + AuthUserFile => $setup->{auth_user_file}, + AuthGroupFile => $setup->{auth_group_file}, IfModules => { 'mod_delay.c' => { @@ -242,7 +331,7 @@ sub ssh2_rewrite_auth { 'mod_rewrite.c' => [ 'RewriteEngine on', - "RewriteLog $log_file", + "RewriteLog $setup->{log_file}", 'RewriteMap lowercase int:tolower', 'RewriteCondition %m USER', @@ -251,14 +340,16 @@ sub ssh2_rewrite_auth { 'mod_sftp.c' => [ "SFTPEngine on", - "SFTPLog $log_file", + "SFTPLog $setup->{log_file}", "SFTPHostKey $rsa_host_key", "SFTPHostKey $dsa_host_key", + "SFTPAuthorizedUserKeys file:~/.authorized_keys", ], }, }; - my ($port, $config_user, $config_group) = config_write($config_file, $config); + my ($port, $config_user, $config_group) = config_write($setup->{config_file}, + $config); # Open pipes, for use between the parent and child processes. Specifically, # the child will indicate when it's done with its test by writing a message @@ -286,14 +377,14 @@ sub ssh2_rewrite_auth { die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str"); } - unless ($ssh2->auth_password(uc($user), $passwd)) { + unless ($ssh2->auth_publickey(uc($setup->{user}), $rsa_pub_key, + $rsa_priv_key)) { my ($err_code, $err_name, $err_str) = $ssh2->error(); die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str"); } $ssh2->disconnect(); }; - if ($@) { $ex = $@; } @@ -302,7 +393,7 @@ sub ssh2_rewrite_auth { $wfh->flush(); } else { - eval { server_wait($config_file, $rfh) }; + eval { server_wait($setup->{config_file}, $rfh) }; if ($@) { warn($@); exit 1; @@ -312,18 +403,147 @@ sub ssh2_rewrite_auth { } # Stop server - server_stop($pid_file); + server_stop($setup->{pid_file}); + $self->assert_child_ok($pid); + + test_cleanup($setup->{log_file}, $ex); +} + +sub ssh2_rewrite_auth_homedir { + my $self = shift; + my $tmpdir = $self->{tmpdir}; + my $setup = test_setup($tmpdir, 'sftp'); + + my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); + my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); + + my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key'); + my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub'); + my $rsa_rfc4716_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/authorized_rsa_keys2'); + + my $authorized_keys = File::Spec->rel2abs("$tmpdir/.authorized_keys"); + unless (copy($rsa_rfc4716_key, $authorized_keys)) { + die("Can't copy $rsa_rfc4716_key to $authorized_keys: $!"); + } + + my $config = { + PidFile => $setup->{pid_file}, + ScoreboardFile => $setup->{scoreboard_file}, + SystemLog => $setup->{log_file}, + TraceLog => $setup->{log_file}, + Trace => 'event:20 ssh2:20 sftp:20 scp:20', + + AuthUserFile => $setup->{auth_user_file}, + AuthGroupFile => $setup->{auth_group_file}, + RewriteHome => 'on', + + IfModules => { + 'mod_delay.c' => { + DelayEngine => 'off', + }, + + 'mod_rewrite.c' => [ + 'RewriteEngine on', + "RewriteLog $setup->{log_file}", + + 'RewriteCondition %m REWRITE_HOME', + 'RewriteRule (.*\/)?(.*) /opt/data/test/$2', + + 'RewriteMap lowercase int:tolower', + 'RewriteCondition %m USER', + 'RewriteRule ^(.*)$ ${lowercase:$1}', + ], + + 'mod_sftp.c' => [ + "SFTPEngine on", + "SFTPLog $setup->{log_file}", + "SFTPHostKey $rsa_host_key", + "SFTPHostKey $dsa_host_key", + "SFTPAuthorizedUserKeys file:~/.authorized_keys", + ], + }, + }; + + my ($port, $config_user, $config_group) = config_write($setup->{config_file}, + $config); + + # Open pipes, for use between the parent and child processes. Specifically, + # the child will indicate when it's done with its test by writing a message + # to the parent. + my ($rfh, $wfh); + unless (pipe($rfh, $wfh)) { + die("Can't open pipe: $!"); + } + + require Net::SSH2; + + my $ex; + + # Fork child + $self->handle_sigchld(); + defined(my $pid = fork()) or die("Can't fork: $!"); + if ($pid) { + eval { + my $ssh2 = Net::SSH2->new(); + + sleep(1); + + unless ($ssh2->connect('127.0.0.1', $port)) { + my ($err_code, $err_name, $err_str) = $ssh2->error(); + die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str"); + } + + if ($ssh2->auth_publickey(uc($setup->{user}), $rsa_pub_key, + $rsa_priv_key)) { + die("Publickey authentication succeeded unexpectedly"); + } + + $ssh2->disconnect(); + }; + if ($@) { + $ex = $@; + } + + $wfh->print("done\n"); + $wfh->flush(); + + } else { + eval { server_wait($setup->{config_file}, $rfh) }; + if ($@) { + warn($@); + exit 1; + } + + exit 0; + } + + # Stop server + server_stop($setup->{pid_file}); $self->assert_child_ok($pid); - if ($ex) { - test_append_logfile($log_file, $ex); - unlink($log_file); + eval { + if (open(my $fh, "< $setup->{log_file}")) { + my $ok = 0; - die($ex); + while (my $line = <$fh>) { + if ($line =~ /error opening SFTPAuthorizedUserKeys .*?: No such file or directory/) { + $ok = 1; + last; + } + } + + close($fh); + + } else { + die("Can't read $setup->{log_file}: $!"); + } + }; + if ($@) { + $ex = $@; } - unlink($log_file); + test_cleanup($setup->{log_file}, $ex); } sub sftp_rewrite_stat {