[proftpd-mod-vroot] 04/05: New upstream version 0.9.4
Francesco Lovergine
frankie at moszumanska.debian.org
Sat Dec 24 19:12:43 UTC 2016
This is an automated email from the git hooks/post-receive script.
frankie pushed a commit to branch master
in repository proftpd-mod-vroot.
commit 807dd9d48ac3ae9d8026ab83f1e7c00083a8f821
Author: Francesco Paolo Lovergine <frankie at debian.org>
Date: Sat Dec 24 20:03:26 2016 +0100
New upstream version 0.9.4
---
mod_vroot.c | 55 +--
mod_vroot.html | 15 +
t/lib/ProFTPD/Tests/Modules/mod_vroot.pm | 789 ++++++++++++++++++++++++++++++-
3 files changed, 820 insertions(+), 39 deletions(-)
diff --git a/mod_vroot.c b/mod_vroot.c
index 3c27be5..b0ce59a 100644
--- a/mod_vroot.c
+++ b/mod_vroot.c
@@ -2,7 +2,7 @@
* ProFTPD: mod_vroot -- a module implementing a virtual chroot capability
* via the FSIO API
*
- * Copyright (c) 2002-2013 TJ Saunders
+ * Copyright (c) 2002-2014 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@
#include "conf.h"
#include "privs.h"
-#define MOD_VROOT_VERSION "mod_vroot/0.9.3"
+#define MOD_VROOT_VERSION "mod_vroot/0.9.4"
/* Make sure the version of proftpd is as necessary. */
#if PROFTPD_VERSION_NUMBER < 0x0001030406
@@ -344,7 +344,6 @@ loop:
* aliases are found.
*/
bufp = buf;
-
start_ptr = path;
while (start_ptr != NULL) {
@@ -430,8 +429,7 @@ static int handle_vroot_alias(void) {
c = find_config(main_server->conf, CONF_PARAM, "VRootAlias", FALSE);
while (c) {
- char src_path[PR_TUNABLE_PATH_MAX+1], dst_path[PR_TUNABLE_PATH_MAX+1],
- vpath[PR_TUNABLE_PATH_MAX+1], *ptr;
+ char src_path[PR_TUNABLE_PATH_MAX+1], dst_path[PR_TUNABLE_PATH_MAX+1], *ptr;
pr_signals_handle();
@@ -458,21 +456,6 @@ static int handle_vroot_alias(void) {
vroot_lookup_path(NULL, dst_path, sizeof(dst_path)-1, ptr,
VROOT_LOOKUP_FL_NO_ALIASES, NULL);
- /* If the vroot of the source path matches the vroot of the destination
- * path, then we have a badly configured VRootAlias, one which is trying
- * to override itself. Need to check for, and reject, such cases.
- */
- vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, src_path,
- VROOT_LOOKUP_FL_NO_ALIASES, NULL);
- if (strcmp(dst_path, vpath) == 0) {
- (void) pr_log_writefile(vroot_logfd, MOD_VROOT_VERSION,
- "alias '%s' maps to its real path '%s' inside the vroot, "
- "ignoring bad alias", dst_path, src_path);
-
- c = find_config_next(c, c->next, CONF_PARAM, "VRootAlias", FALSE);
- continue;
- }
-
if (vroot_alias_pool == NULL) {
vroot_alias_pool = make_sub_pool(session.pool);
pr_pool_tag(vroot_alias_pool, "VRoot Alias Pool");
@@ -1089,6 +1072,7 @@ static int vroot_alias_dirscan(const void *key_data, size_t key_datasz,
void *value_data, size_t value_datasz, void *user_data) {
const char *alias_path = NULL, *dir_path = NULL, *real_path = NULL;
char *ptr = NULL;
+ size_t dir_pathlen;
alias_path = key_data;
real_path = value_data;
@@ -1109,15 +1093,12 @@ static int vroot_alias_dirscan(const void *key_data, size_t key_datasz,
return 0;
}
- /* If the length from the start of the alias path to the last occurring
- * slash is longer than the length of the directory path, then this
- * alias obviously does not occur in this directory.
- */
- if ((ptr - alias_path) > strlen(dir_path)) {
- return 0;
- }
+ dir_pathlen = strlen(dir_path);
- if (strncmp(dir_path, alias_path, (ptr - alias_path)) == 0) {
+ if (strncmp(dir_path, alias_path, dir_pathlen) == 0) {
+ pr_trace_msg(trace_channel, 17,
+ "adding VRootAlias '%s' to list of aliases contained in '%s'",
+ alias_path, dir_path);
*((char **) push_array(vroot_dir_aliases)) = pstrdup(vroot_dir_pool,
ptr + 1);
}
@@ -1127,7 +1108,7 @@ static int vroot_alias_dirscan(const void *key_data, size_t key_datasz,
static int vroot_dirtab_keycmp_cb(const void *key1, size_t keysz1,
const void *key2, size_t keysz2) {
- unsigned int k1, k2;
+ unsigned long k1, k2;
memcpy(&k1, key1, sizeof(k1));
memcpy(&k2, key2, sizeof(k2));
@@ -1136,7 +1117,7 @@ static int vroot_dirtab_keycmp_cb(const void *key1, size_t keysz1,
}
static unsigned int vroot_dirtab_hash_cb(const void *key, size_t keysz) {
- unsigned int h;
+ unsigned long h;
memcpy(&h, key, sizeof(h));
return h;
@@ -1217,7 +1198,7 @@ static void *vroot_opendir(pr_fs_t *fs, const char *orig_path) {
}
if (vroot_aliastab != NULL) {
- unsigned int *cache_dirh;
+ unsigned long *cache_dirh = NULL;
if (vroot_dirtab == NULL) {
vroot_dir_pool = make_sub_pool(session.pool);
@@ -1235,10 +1216,10 @@ static void *vroot_opendir(pr_fs_t *fs, const char *orig_path) {
vroot_dirtab_keycmp_cb);
}
- cache_dirh = palloc(vroot_dir_pool, sizeof(unsigned int));
- *cache_dirh = (unsigned int) dirh;
+ cache_dirh = palloc(vroot_dir_pool, sizeof(unsigned long));
+ *cache_dirh = (unsigned long) dirh;
- if (pr_table_kadd(vroot_dirtab, cache_dirh, sizeof(unsigned int),
+ if (pr_table_kadd(vroot_dirtab, cache_dirh, sizeof(unsigned long),
pstrdup(vroot_dir_pool, vpath), strlen(vpath) + 1) < 0) {
(void) pr_log_writefile(vroot_logfd, MOD_VROOT_VERSION,
"error stashing path '%s' (key %p) in directory table: %s", vpath,
@@ -1339,11 +1320,11 @@ static int vroot_closedir(pr_fs_t *fs, void *dirh) {
res = closedir((DIR *) dirh);
if (vroot_dirtab != NULL) {
- unsigned int lookup_dirh;
+ unsigned long lookup_dirh;
int count;
- lookup_dirh = (unsigned int) dirh;
- (void) pr_table_kremove(vroot_dirtab, &lookup_dirh, sizeof(unsigned int),
+ lookup_dirh = (unsigned long) dirh;
+ (void) pr_table_kremove(vroot_dirtab, &lookup_dirh, sizeof(unsigned long),
NULL);
/* If the dirtab table is empty, destroy the table. */
diff --git a/mod_vroot.html b/mod_vroot.html
index f980f89..c5f03df 100644
--- a/mod_vroot.html
+++ b/mod_vroot.html
@@ -196,11 +196,26 @@ the <code>mod_vroot.c</code> file into:
Then follow the normal steps for using third-party modules in proftpd:
<pre>
./configure --with-modules=mod_vroot
+</pre>
+To build <code>mod_vroot</code> as a DSO module:
+<pre>
+ ./configure --enable-dso --with-shared=mod_vroot
+</pre>
+Then follow the usual steps:
+<pre>
make
make install
</pre>
<p>
+For those with an existing ProFTPD installation, you can use the
+<code>prxs</code> tool to add <code>mod_vroot</code>, as a DSO module, to
+your existing server:
+<pre>
+ # prxs -c -i -d mod_vroot.c
+</pre>
+
+<p>
<hr>
Author: <i>$Author: tj $</i><br>
Last Updated: <i>$Date: 2009/10/19 16:30:18 $</i><br>
diff --git a/t/lib/ProFTPD/Tests/Modules/mod_vroot.pm b/t/lib/ProFTPD/Tests/Modules/mod_vroot.pm
index 010070b..9c542db 100644
--- a/t/lib/ProFTPD/Tests/Modules/mod_vroot.pm
+++ b/t/lib/ProFTPD/Tests/Modules/mod_vroot.pm
@@ -29,6 +29,11 @@ my $TESTS = {
test_class => [qw(forking)],
},
+ vroot_anon_limit_write_allow_stor => {
+ order => ++$order,
+ test_class => [qw(forking)],
+ },
+
vroot_symlink => {
order => ++$order,
test_class => [qw(forking)],
@@ -328,12 +333,37 @@ my $TESTS = {
test_class => [qw(forking)],
},
+ # See:
+ # https://github.com/Castaglia/proftpd-mod_vroot/issues/4
+ vroot_alias_bad_src_dst_check_bug4 => {
+ order => ++$order,
+ test_class => [qw(bug forking)],
+ },
+
+ # See:
+ # https://github.com/Castaglia/proftpd-mod_vroot/issues/5
+ vroot_alias_bad_alias_dirscan_bug5 => {
+ order => ++$order,
+ test_class => [qw(bug forking)],
+ },
+
+ # See:
+ # https://github.com/proftpd/proftpd/issues/59
+ vroot_alias_enametoolong_bug59 => {
+ order => ++$order,
+ test_class => [qw(bug forking)],
+ },
+
};
sub new {
return shift()->SUPER::new(@_);
}
+sub tear_down {
+ rmtree('/tmp/vroot.d');
+}
+
sub list_tests {
return testsuite_get_runnable_tests($TESTS);
@@ -964,6 +994,185 @@ EOC
unlink($log_file);
}
+sub vroot_anon_limit_write_allow_stor {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+
+ my $config_file = "$tmpdir/vroot.conf";
+ my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
+ my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
+
+ my $log_file = test_get_logfile();
+
+ my $auth_user_file = File::Spec->rel2abs("$tmpdir/vroot.passwd");
+ my $auth_group_file = File::Spec->rel2abs("$tmpdir/vroot.group");
+
+ my ($user, $group) = config_get_identity();
+ my $passwd = 'test';
+ my $anon_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = $<;
+ my $gid = $(;
+
+ my $uploads_dir = File::Spec->rel2abs("$anon_dir/uploads");
+ mkpath($uploads_dir);
+
+ my $test_file = File::Spec->rel2abs("$uploads_dir/test.txt");
+
+ # 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, $anon_dir, $uploads_dir)) {
+ die("Can't set perms on $anon_dir to 0755: $!");
+ }
+
+ unless (chown($uid, $gid, $anon_dir, $uploads_dir)) {
+ die("Can't set owner of $anon_dir to $uid/$gid: $!");
+ }
+ }
+
+ auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, '/tmp',
+ '/bin/bash');
+ auth_group_write($auth_group_file, $group, $gid, $user);
+
+ # Test this config:
+ #
+ # <Anonymous>
+ # <Limit WRITE SITE_CHMOD>
+ # DenyAll
+ # </Limit>
+ #
+ # <Directory uploads/*>
+ # <Limit STOR>
+ # AllowAll
+ # </Limit>
+ # </Directory>
+ # </Anonymous>
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ },
+
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+ },
+ };
+
+ my ($port, $config_user, $config_group) = config_write($config_file, $config);
+
+ if (open(my $fh, ">> $config_file")) {
+ print $fh <<EOC;
+<Anonymous $anon_dir>
+ User $user
+ Group $group
+
+ RequireValidShell off
+
+ <Limit WRITE SITE_CHMOD>
+ DenyAll
+ </Limit>
+
+ # Ideally there would be no leading slash here, but because of how
+ # mod_vroot alters things (see Issue #1), the leading slash makes
+ # the test succeed.
+ <Directory /uploads/*>
+ <Limit STOR>
+ AllowAll
+ </Limit>
+ </Directory>
+
+</Anonymous>
+
+EOC
+ unless (close($fh)) {
+ die("Can't write $config_file: $!");
+ }
+
+ } else {
+ die("Can't open $config_file: $!");
+ }
+
+ # 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: $!");
+ }
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
+
+ my $conn = $client->stor_raw('uploads/test.txt');
+ unless ($conn) {
+ die("STOR uploads/test.txt failed:" . $client->response_code() . " " .
+ $client->response_msg());
+ }
+
+ my $buf = "Hello, World!\n";
+ $conn->write($buf, length($buf), 15);
+ eval { $conn->close() };
+
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+
+ $self->assert_transfer_ok($resp_code, $resp_msg);
+
+ $client->quit();
+
+ $self->assert(-f $test_file,
+ test_msg("File $test_file does not exist as expected"));
+ };
+
+ if ($@) {
+ $ex = $@;
+ }
+
+ $wfh->print("done\n");
+ $wfh->flush();
+
+ } else {
+ eval { server_wait($config_file, $rfh) };
+ if ($@) {
+ warn($@);
+ exit 1;
+ }
+
+ exit 0;
+ }
+
+ # Stop server
+ server_stop($pid_file);
+
+ $self->assert_child_ok($pid);
+
+ if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
sub vroot_symlink {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -1033,7 +1242,7 @@ sub vroot_symlink {
ScoreboardFile => $scoreboard_file,
SystemLog => $log_file,
TraceLog => $log_file,
- Trace => 'fsio:10',
+ Trace => 'fsio:10 vroot:20',
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
@@ -1068,6 +1277,8 @@ sub vroot_symlink {
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
+ sleep(1);
+
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
$client->login($user, $passwd);
@@ -1123,7 +1334,7 @@ sub vroot_symlink {
$wfh->flush();
} else {
- eval { server_wait($config_file, $rfh) };
+ eval { server_wait($config_file, $rfh, 15) };
if ($@) {
warn($@);
exit 1;
@@ -11862,4 +12073,578 @@ sub vroot_alias_var_u_symlink_dir {
unlink($log_file);
}
+sub vroot_alias_bad_src_dst_check_bug4 {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+
+ my $config_file = "$tmpdir/vroot.conf";
+ my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
+ my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
+
+ my $log_file = test_get_logfile();
+
+ my $auth_user_file = File::Spec->rel2abs("$tmpdir/vroot.passwd");
+ my $auth_group_file = File::Spec->rel2abs("$tmpdir/vroot.group");
+
+ my $user = 'proftpd';
+ my $passwd = 'test';
+ my $group = 'ftpd';
+ my $home_dir = File::Spec->rel2abs("$tmpdir/$user");
+ mkpath($home_dir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # In order for the real /tmp/vroot.d directory to be visible, via
+ # VRootAlias, within the vroot, the leading /tmp directory needs to
+ # actually exist with the vroot. In other words, the path needs to be
+ # real, even if the leaf is virtual.
+ my $user_tmpdir = File::Spec->rel2abs("$home_dir/tmp");
+ mkpath($user_tmpdir);
+
+ my $test_dir = File::Spec->rel2abs("/tmp/vroot.d");
+ mkpath($test_dir);
+
+ my $test_file = File::Spec->rel2abs("$test_dir/test.txt");
+ if (open(my $fh, "> $test_file")) {
+ close($fh);
+
+ } else {
+ die("Can't open $test_file: $!");
+ }
+
+ # 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, $user_tmpdir, $test_dir)) {
+ die("Can't set perms on $home_dir to 0755: $!");
+ }
+
+ unless (chown($uid, $gid, $home_dir, $user_tmpdir, $test_dir)) {
+ die("Can't set owner of $home_dir to $uid/$gid: $!");
+ }
+ }
+
+ auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
+ '/bin/bash');
+ auth_group_write($auth_group_file, $group, $gid, $user);
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:20 vroot:20',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+ ShowSymlinks => 'off',
+
+ IfModules => {
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$test_dir ~/tmp/vroot.d",
+ },
+
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+ },
+ };
+
+ my ($port, $config_user, $config_group) = config_write($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: $!");
+ }
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
+
+ my ($resp_code, $resp_msg) = $client->pwd();
+
+ my $expected;
+
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "\"/\" is the current directory";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ $client->cwd('/tmp/vroot.d');
+
+ my $conn = $client->list_raw();
+ unless ($conn) {
+ die("Failed to LIST: " . $client->response_code() . " " .
+ $client->response_msg());
+ }
+
+ my $buf;
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
+
+ # We have to be careful of the fact that readdir returns directory
+ # entries in an unordered fashion.
+ my $res = {};
+ my $lines = [split(/\n/, $buf)];
+ foreach my $line (@$lines) {
+ if ($line =~ /^(\S+)\s+\d+\s+\S+\s+\S+\s+.*?\s+(\S+)$/) {
+ $res->{$2} = $1;
+ }
+ }
+
+ unless (scalar(keys(%$res)) > 0) {
+ die("LIST data unexpectedly empty");
+ }
+
+ $expected = {
+ 'test.txt' => 1,
+ };
+
+ my $ok = 1;
+ my $mismatch;
+ foreach my $name (keys(%$res)) {
+ unless (defined($expected->{$name})) {
+ $mismatch = $name;
+ $ok = 0;
+ last;
+ }
+ }
+
+ unless ($ok) {
+ die("Unexpected name '$mismatch' appeared in LIST data")
+ }
+
+ my $mode = '-rw-r--r--';
+ $self->assert($mode eq $res->{'test.txt'},
+ test_msg("Expected '$mode' for 'test.txt', got '$res->{'test.txt'}'"));
+
+ $client->quit();
+ };
+
+ if ($@) {
+ $ex = $@;
+ }
+
+ $wfh->print("done\n");
+ $wfh->flush();
+
+ } else {
+ eval { server_wait($config_file, $rfh) };
+ if ($@) { warn($@);
+ exit 1;
+ }
+
+ exit 0;
+ }
+
+ # Stop server
+ server_stop($pid_file);
+
+ $self->assert_child_ok($pid);
+
+ if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_bad_alias_dirscan_bug5 {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+
+ my $config_file = "$tmpdir/vroot.conf";
+ my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
+ my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
+
+ my $log_file = test_get_logfile();
+
+ my $auth_user_file = File::Spec->rel2abs("$tmpdir/vroot.passwd");
+ my $auth_group_file = File::Spec->rel2abs("$tmpdir/vroot.group");
+
+ my $user = 'proftpd';
+ my $passwd = 'test';
+ my $group = 'ftpd';
+ my $home_dir = File::Spec->rel2abs("$tmpdir/$user");
+ mkpath($home_dir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # In order for the real /tmp/vroot.d directory to be visible, via
+ # VRootAlias, within the vroot, the leading /tmp directory needs to
+ # actually exist with the vroot. In other words, the path needs to be
+ # real, even if the leaf is virtual.
+ my $user_tmpdir = File::Spec->rel2abs("$home_dir/tmp");
+ mkpath($user_tmpdir);
+
+ my $test_dir = File::Spec->rel2abs("/tmp/vroot.d");
+ mkpath($test_dir);
+
+ my $test_file = File::Spec->rel2abs("$test_dir/test.txt");
+ if (open(my $fh, "> $test_file")) {
+ close($fh);
+
+ } else {
+ die("Can't open $test_file: $!");
+ }
+
+ # 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, $user_tmpdir, $test_dir)) {
+ die("Can't set perms on $home_dir to 0755: $!");
+ }
+
+ unless (chown($uid, $gid, $home_dir, $user_tmpdir, $test_dir)) {
+ die("Can't set owner of $home_dir to $uid/$gid: $!");
+ }
+ }
+
+ auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
+ '/bin/bash');
+ auth_group_write($auth_group_file, $group, $gid, $user);
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:20 vroot:20',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+ ShowSymlinks => 'off',
+
+ IfModules => {
+ 'mod_vroot.c' => [
+ 'VRootEngine on',
+ "VRootLog $log_file",
+ 'DefaultRoot ~',
+ "VRootAlias $test_dir ~/vroot.d",
+ "VRootAlias $test_dir ~/tmp/vroot.d",
+ ],
+
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+ },
+ };
+
+ my ($port, $config_user, $config_group) = config_write($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: $!");
+ }
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
+
+ my ($resp_code, $resp_msg) = $client->pwd();
+
+ my $expected;
+
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "\"/\" is the current directory";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ $client->cwd('/tmp');
+
+ my $conn = $client->list_raw();
+ unless ($conn) {
+ die("Failed to LIST: " . $client->response_code() . " " .
+ $client->response_msg());
+ }
+
+ my $buf;
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
+
+ # We have to be careful of the fact that readdir returns directory
+ # entries in an unordered fashion.
+ my $res = {};
+ my $lines = [split(/\n/, $buf)];
+ foreach my $line (@$lines) {
+ if ($line =~ /^(\S+)\s+\d+\s+\S+\s+\S+\s+.*?\s+(\S+)$/) {
+ $res->{$2} = $1;
+ }
+ }
+
+ unless (scalar(keys(%$res)) > 0) {
+ die("LIST data unexpectedly empty");
+ }
+
+ $expected = {
+ 'vroot.d' => 1,
+ };
+
+ my $ok = 1;
+ my $mismatch;
+ foreach my $name (keys(%$res)) {
+ unless (defined($expected->{$name})) {
+ $mismatch = $name;
+ $ok = 0;
+ last;
+ }
+ }
+
+ unless ($ok) {
+ die("Unexpected name '$mismatch' appeared in LIST data")
+ }
+
+ my $mode = 'drwxr-xr-x';
+ $self->assert($mode eq $res->{'vroot.d'},
+ test_msg("Expected '$mode' for 'vroot.d', got '$res->{'vroot.d'}'"));
+
+ $client->quit();
+ };
+
+ if ($@) {
+ $ex = $@;
+ }
+
+ $wfh->print("done\n");
+ $wfh->flush();
+
+ } else {
+ eval { server_wait($config_file, $rfh) };
+ if ($@) { warn($@);
+ exit 1;
+ }
+
+ exit 0;
+ }
+
+ # Stop server
+ server_stop($pid_file);
+
+ $self->assert_child_ok($pid);
+
+ if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_enametoolong_bug59 {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+
+ my $config_file = "$tmpdir/vroot.conf";
+ my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
+ my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
+
+ my $log_file = test_get_logfile();
+
+ my $auth_user_file = File::Spec->rel2abs("$tmpdir/vroot.passwd");
+ my $auth_group_file = File::Spec->rel2abs("$tmpdir/vroot.group");
+
+ my $user = 'proftpd';
+ my $passwd = 'test';
+ my $group = 'ftpd';
+ my $home_dir = File::Spec->rel2abs("$tmpdir/$user");
+ mkpath($home_dir);
+ my $uid = 500;
+ my $gid = 500;
+
+ my $test_dir = File::Spec->rel2abs("/tmp/vroot.d/0001a/10001a/encoding/input");
+ mkpath($test_dir);
+
+ my $test_file = File::Spec->rel2abs("$test_dir/asgard");
+ if (open(my $fh, "> $test_file")) {
+ close($fh);
+
+ } else {
+ die("Can't open $test_file: $!");
+ }
+
+ # 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, $test_dir)) {
+ die("Can't set perms on $home_dir to 0755: $!");
+ }
+
+ unless (chown($uid, $gid, $home_dir, $test_dir)) {
+ die("Can't set owner of $home_dir to $uid/$gid: $!");
+ }
+ }
+
+ auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
+ '/bin/bash');
+ auth_group_write($auth_group_file, $group, $gid, $user);
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:20 vroot:20',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+ ShowSymlinks => 'off',
+
+ IfModules => {
+ 'mod_vroot.c' => [
+ 'VRootEngine on',
+ "VRootLog $log_file",
+ 'DefaultRoot ~',
+ "VRootAlias /tmp ~/tmp-vroot-alias",
+ "VRootAlias $test_dir ~/0001a-input",
+ ],
+
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+ },
+ };
+
+ my ($port, $config_user, $config_group) = config_write($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: $!");
+ }
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
+
+ my ($resp_code, $resp_msg) = $client->pwd();
+
+ my $expected;
+
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "\"/\" is the current directory";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ my $conn = $client->mlsd_raw('0001a-input');
+ unless ($conn) {
+ die("Failed to MLSD: " . $client->response_code() . " " .
+ $client->response_msg());
+ }
+
+ my $buf;
+ $conn->read($buf, 8192, 30);
+ eval { $conn->close() };
+
+ # We have to be careful of the fact that readdir returns directory
+ # entries in an unordered fashion.
+ my $res = {};
+ my $lines = [split(/\n/, $buf)];
+ foreach my $line (@$lines) {
+ if ($line =~ /^modify=\S+;perm=\S+;type=\S+;unique=\S+;UNIX\.group=\d+;UNIX\.mode=\d+;UNIX.owner=\d+; (.*?)$/) {
+ $res->{$1} = 1;
+ }
+ }
+
+ unless (scalar(keys(%$res)) > 0) {
+ die("MLSD data unexpectedly empty");
+ }
+
+ $expected = {
+ '.' => 1,
+ '..' => 1,
+ 'asgard' => 1,
+ };
+
+ my $ok = 1;
+ my $mismatch;
+ foreach my $name (keys(%$res)) {
+ unless (defined($expected->{$name})) {
+ $mismatch = $name;
+ $ok = 0;
+ last;
+ }
+ }
+
+ unless ($ok) {
+ die("Unexpected name '$mismatch' appeared in MLSD data")
+ }
+
+ $client->quit();
+ };
+
+ if ($@) {
+ $ex = $@;
+ }
+
+ $wfh->print("done\n");
+ $wfh->flush();
+
+ } else {
+ eval { server_wait($config_file, $rfh) };
+ if ($@) { warn($@);
+ exit 1;
+ }
+
+ exit 0;
+ }
+
+ # Stop server
+ server_stop($pid_file);
+
+ $self->assert_child_ok($pid);
+
+ if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
1;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-proftpd/proftpd-mod-vroot.git
More information about the Pkg-proftpd-maintainers
mailing list