Skip to content

Commit

Permalink
Adding regression tests showing mod_sftp+mod_rewrite working as expec…
Browse files Browse the repository at this point in the history
…ted.

Fixed related typo in the `mod_auth` docs.
  • Loading branch information
Castaglia committed Aug 10, 2021
1 parent 842f03f commit 106c556
Show file tree
Hide file tree
Showing 2 changed files with 263 additions and 43 deletions.
2 changes: 1 addition & 1 deletion doc/modules/mod_auth.html
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ <h3><a name="RewriteHome">RewriteHome</a></h3>
<pre>
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine on
RewrlteLog /path/to/rewrite.log
RewriteLog /path/to/rewrite.log

RewriteCondition %m REWRITE_HOME
RewriteRule (.*) /my/new/prefix$1
Expand Down
304 changes: 262 additions & 42 deletions tests/t/lib/ProFTPD/Tests/Modules/mod_sftp/rewrite.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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)],
},
Expand Down Expand Up @@ -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' => {
Expand All @@ -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',
Expand All @@ -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
Expand Down Expand Up @@ -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 = $@;
}
Expand All @@ -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;
Expand All @@ -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 {
Expand Down

0 comments on commit 106c556

Please sign in to comment.