[SCM] proftpd-mod-vroot branch, master, updated. debian/0.9.2-1-11-g9649971
Mahyuddin Susanto
udienz at gmail.com
Fri Dec 20 04:10:45 UTC 2013
The following commit has been merged in the master branch:
commit 74a910471e7afc5114eaf45ffd7fff62bc8a5eb4
Author: Mahyuddin Susanto <udienz at gmail.com>
Date: Fri Dec 20 11:09:53 2013 +0700
Imported Upstream version 0.9.3
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5fd47f1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+proftpd-mod_vroot
+=================
+
+ProFTPD module that creates "virtual" chroots
\ No newline at end of file
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 423b64f..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,24 +0,0 @@
-proftpd-mod-vroot (0.9.2-3) UNRELEASED; urgency=low
-
- * Removing libacl1-dev as BD and increasing proftpd-dev to (>= 1.3.4~rc3-2~)
- * Moved to binNMU
- * Fixed spelling-error-in-description lintian message
- * Fixed unversioned-copyright-format
-
- -- Fabrizio Regalli <fabreg at fabreg.it> Tue, 22 Nov 2011 15:51:26 +0100
-
-proftpd-mod-vroot (0.9.2-2) unstable; urgency=low
-
- * Fixed spelling-error-in-description lintian message
- * Update d/copyright to latest .174 DEP5 revision
- * Fixed timewarp-standards-version lintian message
-
- -- Fabrizio Regalli <fabreg at fabreg.it> Thu, 29 Sep 2011 15:24:55 +0200
-
-proftpd-mod-vroot (0.9.2-1) unstable; urgency=low
-
- * Initial Release. (closes: #618765)
- * Added doc-base
- * Added dh_clean to d/rules
-
- -- Fabrizio Regalli <fabreg at fabreg.it> Thu, 15 Mar 2011 18:14:35 +0100
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index 7f8f011..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-7
diff --git a/debian/control b/debian/control
deleted file mode 100644
index a1b1cb0..0000000
--- a/debian/control
+++ /dev/null
@@ -1,24 +0,0 @@
-Source: proftpd-mod-vroot
-Section: net
-Priority: optional
-Maintainer: ProFTPD Maintainance Team <pkg-proftpd-maintainers at lists.alioth.debian.org>
-Uploaders: Fabrizio Regalli <fabreg at fabreg.it>,
- Francesco Paolo Lovergine <frankie at debian.org>
-DM-Upload-Allowed: yes
-Build-Depends: debhelper (>= 7.0.50~), proftpd-dev (>= 1.3.4~rc3-2~)
-Standards-Version: 3.9.2
-Homepage: http://www.castaglia.org/proftpd/modules/mod_vroot.html
-Vcs-Git: git://git.debian.org/pkg-proftpd/proftpd-mod-vroot.git
-Vcs-Browser: http://git.debian.org/?p=pkg-proftpd/proftpd-mod-vroot.git;a=summary
-
-
-Package: proftpd-mod-vroot
-Architecture: any
-Depends: proftpd-basic (>= 1.3.4~rc2-2~), ${misc:Depends}, ${shlibs:Depends}, ${proftpd:Depends}
-Breaks: proftpd-basic (<< 1.3.4~rc2-2~)
-Description: ProFTPD module mod_vroot
- The purpose of this module to is to implement a virtual chroot
- capability that does not require root privileges.
- The mod_vroot module provides this capability by using ProFTPD's
- FS API. It also allows one to map a directory out of the user chroot
- as an alias in the chroot for sharing common directories.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index cf44c82..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,30 +0,0 @@
-Format: http://anonscm.debian.org/viewvc/dep/web/deps/dep5.mdwn?revision=174
-Upstream-Name: mod_vroot
-Upstream-Contact: TJ Saunders
-Source: http://www.castaglia.org/proftpd/modules/mod_vroot.html
-
-Files: *
-Copyright: 2007-2010, TJ Saunders
-License: GPL-2+
-
-License: GPL-2+
- This package is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- .
- This package is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- .
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
- .
- On Debian systems, the complete text of the GNU General
- Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
-
-Files: debian/*
-Copyright: 2011, Fabrizio Regalli <fabreg at fabreg.it>
-License: GPL-2+
-
diff --git a/debian/proftpd-mod-vroot.dirs b/debian/proftpd-mod-vroot.dirs
deleted file mode 100644
index f0e8d4e..0000000
--- a/debian/proftpd-mod-vroot.dirs
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/lib/proftpd
-usr/share/proftpd/templates
diff --git a/debian/proftpd-mod-vroot.doc-base b/debian/proftpd-mod-vroot.doc-base
deleted file mode 100644
index 8ce9ae0..0000000
--- a/debian/proftpd-mod-vroot.doc-base
+++ /dev/null
@@ -1,9 +0,0 @@
-Document: proftpd-mod-vroot
-Title: Documentation for the mod_vroot ProFTPD
-Author:
-Abstract: Configuration reference, modules documentation, FAQs and HOWTOs
-Section: System/Administration
-
-Format: HTML
-Index: /usr/share/doc/proftpd-mod-vroot/mod_vroot.html
-Files: /usr/share/doc/proftpd-mod-vroot/*.html
diff --git a/debian/proftpd-mod-vroot.docs b/debian/proftpd-mod-vroot.docs
deleted file mode 100644
index 3048e6b..0000000
--- a/debian/proftpd-mod-vroot.docs
+++ /dev/null
@@ -1 +0,0 @@
-mod_vroot.html
diff --git a/debian/proftpd-mod-vroot.install b/debian/proftpd-mod-vroot.install
deleted file mode 100644
index 6b6e368..0000000
--- a/debian/proftpd-mod-vroot.install
+++ /dev/null
@@ -1 +0,0 @@
-debian/templates/vroot.conf usr/share/doc/proftpd-mod-vroot/
diff --git a/debian/proftpd-mod-vroot.links b/debian/proftpd-mod-vroot.links
deleted file mode 100644
index 53f7a33..0000000
--- a/debian/proftpd-mod-vroot.links
+++ /dev/null
@@ -1 +0,0 @@
-usr/share/doc/proftpd-mod-vroot/vroot.conf usr/share/proftpd/templates/vroot.conf
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index 3c139c8..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-
-export DH_VERBOSE=1
-VERSION=$(shell grep PROFTPD_VERSION_TEXT /usr/include/proftpd/version.h|cut -d\" -f2)
-MODULE_NAME=mod_vroot
-DEBNAME=proftpd-mod-vroot
-
-%:
- dh $@
-
-override_dh_auto_build:
- DESTDIR=$(CURDIR)/debian/$(DEBNAME) prxs -c $(MODULE_NAME).c
-
-override_dh_auto_install:
- DESTDIR=$(CURDIR)/debian/$(DEBNAME) prxs -i -c $(MODULE_NAME).c
- rm -f $(CURDIR)/debian/$(DEBNAME)/usr/lib/proftpd/*.la \
- $(CURDIR)/debian/$(DEBNAME)/usr/lib/proftpd/*.a
-
-override_dh_gencontrol:
- cat /usr/share/proftpd/proftpd-substvars >>$(CURDIR)/debian/$(DEBNAME).substvars
- dh_gencontrol
-
-clean:
- dh_clean
- $(RM) $(MODULE_NAME).a *.o *.la *.lo
- $(LIBTOOL) --mode=clean $(RM) "$(MODULE_NAME).o"
- $(LIBTOOL) --mode=clean $(RM) `echo "$(MODULE_NAME).la" | sed 's/\.la$\/.lo/g'`
- $(RM) -rf $(CURDIR)/debian/proftpd-mod-vroot $(CURDIR)/debian/*.log $(CURDIR)/debian/files $(CURDIR)/debian/$(DEBNAME).substvars
-
-distclean: clean
- $(RM) -r .libs/
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/templates/vroot.conf b/debian/templates/vroot.conf
deleted file mode 100644
index ed7533f..0000000
--- a/debian/templates/vroot.conf
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# Proftpd sample configuration for vroot.
-#
-
-<IfModule mod_vroot.c>
-
-# VRootAlias
-# Syntax: VRootAlias src-path dst-path
-# Default: None
-# The VRootAlias directive is used to create an "alias" of a directory outside of the chroot area into
-# the chroot. The dst-path parameter is a relative path, relative to the chroot area (i.e. the directory
-# in which the session starts). The src-path parameter, on the other hand, is an absolute path, and may be to a file or directory.
-# For example, you might map a shared upload directory into a user's home directory using:
-# <IfModule mod_vroot.c>
-# VRootEngine on
-#
-# DefaultRoot ~
-# VRootAlias /var/ftp/upload ~/upload
-# </IfModule>
-# This will automatically create an "upload" directory to appear in the chroot area (in this case, the user's home directory).
-# Note that this directive will not work if the VRootServerRoot is used.
-
-# VRootEngine
-# Syntax: VRootEngine on|off
-# Default: None
-# The VRootEngine directive enables the virtual chroot engine implemented by mod_vroot.
-# If enabled, the virtual chroot will be used in place of the operating system's chroot(2).
-# This directive affects any DefaultRoot directives and any <Anonymous> contexts within the
-# server context in which the VRootEngine directive appears.
-VRootEngine on
-DefaultRoot ~
-VRootAlias /var/ftp/upload ~/upload
-
-# VRootLog
-# Syntax: VRootLog file
-# Default: None
-# The VRootLog directive is used to specify a log file for mod_vroot's reporting on a
-# per-server basis. The file parameter given must be the full path to the file to use for logging.
-
-# VRootOptions
-# Syntax: VRootOptions opt1 ...
-# Default: None
-# The VRootOptions directive is used to configure various optional behavior of mod_vroot.
-# Example:
-# VRootOptions allowSymlinks
-# The currently implemented options are:
-# * allowSymlinks
-# Normally, any symlinks that point outside of the vroot area simply do not work.
-# When the allowSymlinks option is enabled, these symlinks will be allowed.
-# Note that by enabling symlinks, the efficacy of the vroot "jail" is reduced.
-
-# VRootServerRoot
-# Syntax: VRootServerRoot path
-# Default: None
-# The VRootServerRoot directive is used to configure a directory to which the mod_vroot module will perform a real chroot.
-# The idea is that each <VirtualHost> can have its own directory to which a real chroot(2) system call is made;
-# the user-specific home directories will be virtual roots underneath this directory. Thus some measure of security,
-# via the chroot(2) system call, is provided by the kernel, while still allowing symlinked shared folders among users of this <VirtualHost>.
-# For example:
-# <VirtualHost a.b.c.d>
-# VRootEngine on
-# VRootServerRoot /etc/ftpd/a.b.c.d/
-# VRootOptions allowSymlinks
-# DefaultRoot ~
-# ...
-#
-# </VirtualHost>
-
-</IfModule>
-
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index 2db693a..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=3
-http://githubredir.debian.net/github/Castaglia/proftpd-mod_vroot/ (.*).tar.gz
\ No newline at end of file
diff --git a/mod_vroot.c b/mod_vroot.c
index 0b864ab..3c27be5 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-2011 TJ Saunders
+ * Copyright (c) 2002-2013 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,11 +32,11 @@
#include "conf.h"
#include "privs.h"
-#define MOD_VROOT_VERSION "mod_vroot/0.9.2"
+#define MOD_VROOT_VERSION "mod_vroot/0.9.3"
/* Make sure the version of proftpd is as necessary. */
-#if PROFTPD_VERSION_NUMBER < 0x0001030201
-# error "ProFTPD 1.3.2rc1 or later required"
+#if PROFTPD_VERSION_NUMBER < 0x0001030406
+# error "ProFTPD 1.3.4b or later required"
#endif
static const char *vroot_log = NULL;
@@ -53,9 +53,16 @@ static pr_table_t *vroot_aliastab = NULL;
static pool *vroot_dir_pool = NULL;
static pr_table_t *vroot_dirtab = NULL;
+#if PROFTPD_VERSION_NUMBER >= 0x0001030407
+static int vroot_use_mkdtemp = FALSE;
+#endif /* ProFTPD 1.3.4c or later */
+
static unsigned int vroot_opts = 0;
#define VROOT_OPT_ALLOW_SYMLINKS 0x0001
+/* vroot_realpath() flags */
+#define VROOT_REALPATH_FL_ABS_PATH 0x001
+
/* vroot_lookup_path() flags */
#define VROOT_LOOKUP_FL_NO_ALIASES 0x0001
@@ -68,8 +75,10 @@ static int vroot_is_alias(const char *);
*/
static void strmove(register char *dst, register const char *src) {
- if (!dst || !src)
+ if (dst == NULL ||
+ src == NULL) {
return;
+ }
while (*src != 0) {
*dst++ = *src++;
@@ -79,25 +88,31 @@ static void strmove(register char *dst, register const char *src) {
}
static void vroot_clean_path(char *path) {
- char *p;
+ char *p = NULL;
- if (path == NULL || *path == 0)
+ if (path == NULL ||
+ *path == 0) {
return;
+ }
- while ((p = strstr(path, "//")) != NULL)
+ while ((p = strstr(path, "//")) != NULL) {
strmove(p, p + 1);
+ }
- while ((p = strstr(path, "/./")) != NULL)
+ while ((p = strstr(path, "/./")) != NULL) {
strmove(p, p + 2);
+ }
- while (strncmp(path, "../", 3) == 0)
+ while (strncmp(path, "../", 3) == 0) {
path += 3;
+ }
p = strstr(path, "/../");
if (p != NULL) {
if (p == path) {
- while (strncmp(path, "/../", 4) == 0)
+ while (strncmp(path, "/../", 4) == 0) {
strmove(path, path + 3);
+ }
p = strstr(path, "/../");
}
@@ -105,14 +120,19 @@ static void vroot_clean_path(char *path) {
while (p != NULL) {
char *next_elem = p + 4;
- if (p != path && *p == '/')
+ if (p != path &&
+ *p == '/') {
p--;
+ }
- while (p != path && *p != '/')
+ while (p != path &&
+ *p != '/') {
p--;
+ }
- if (*p == '/')
+ if (*p == '/') {
p++;
+ }
strmove(p, next_elem);
p = strstr(path, "/../");
@@ -124,36 +144,45 @@ static void vroot_clean_path(char *path) {
if (*p == '.') {
p++;
- if (*p == '\0')
+ if (*p == '\0') {
return;
+ }
if (*p == '/') {
- while (*p == '/')
+ while (*p == '/') {
p++;
+ }
strmove(path, p);
}
}
- if (*p == '\0')
+ if (*p == '\0') {
return;
+ }
p = path + strlen(path) - 1;
- if (*p != '.' || p == path)
+ if (*p != '.' ||
+ p == path) {
return;
+ }
p--;
- if (*p == '/' || p == path) {
+ if (*p == '/' ||
+ p == path) {
p[1] = '\0';
return;
}
- if (*p != '.' || p == path)
+ if (*p != '.' ||
+ p == path) {
return;
+ }
p--;
- if (*p != '/')
+ if (*p != '/') {
return;
+ }
*p = '\0';
p = strrchr(path, '/');
@@ -166,6 +195,38 @@ static void vroot_clean_path(char *path) {
p[1] = '\0';
}
+static char *vroot_realpath(pool *p, const char *path, int flags) {
+ char *real_path = NULL;
+ size_t real_pathlen;
+
+ if (flags & VROOT_REALPATH_FL_ABS_PATH) {
+ /* If not an absolute path, prepend the current location. */
+ if (*path != '/') {
+ real_path = pdircat(p, pr_fs_getvwd(), path, NULL);
+
+ } else {
+ real_path = pstrdup(p, path);
+ }
+
+ } else {
+ real_path = pstrdup(p, path);
+ }
+
+ vroot_clean_path(real_path);
+
+ /* If the given path ends in a slash, remove it. The handling of
+ * VRootAliases is sensitive to such things.
+ */
+ real_pathlen = strlen(real_path);
+ if (real_pathlen > 1 &&
+ real_path[real_pathlen-1] == '/') {
+ real_path[real_pathlen-1] = '\0';
+ real_pathlen--;
+ }
+
+ return real_path;
+}
+
static int vroot_lookup_path(pool *p, char *path, size_t pathlen,
const char *dir, int flags, char **alias_path) {
char buf[PR_TUNABLE_PATH_MAX + 1], *bufp = NULL;
@@ -219,13 +280,12 @@ loop:
} else if (*bufp == '/') {
snprintf(path, pathlen, "%s/", vroot_base);
-
bufp += 1;
goto loop;
} else if (*bufp != '\0') {
size_t buflen, tmplen;
- char *ptr;
+ char *ptr = NULL;
ptr = strstr(bufp, "..");
if (ptr != NULL) {
@@ -280,9 +340,15 @@ loop:
if (vroot_aliastab != NULL) {
char *start_ptr = NULL, *end_ptr = NULL, *src_path = NULL;
+ /* buf is used here for storing the "suffix", to be appended later when
+ * aliases are found.
+ */
+ bufp = buf;
+
start_ptr = path;
+
while (start_ptr != NULL) {
- char *ptr;
+ char *ptr = NULL;
pr_signals_handle();
@@ -312,8 +378,8 @@ loop:
sstrncpy(path, src_path, pathlen);
if (end_ptr != NULL) {
- sstrcat(path, "/", pathlen);
- sstrcat(path, end_ptr + 1, pathlen);
+ /* Now tack on our suffix from the scratchpad. */
+ sstrcat(path, bufp, pathlen);
}
break;
@@ -334,6 +400,8 @@ loop:
break;
}
+ /* Store the suffix in the buf scratchpad. */
+ sstrncpy(buf, ptr, sizeof(buf));
end_ptr = ptr;
*end_ptr = '\0';
}
@@ -354,7 +422,7 @@ static int vroot_is_alias(const char *path) {
static int handle_vroot_alias(void) {
config_rec *c;
- pool *tmp_pool;
+ pool *tmp_pool = NULL;
/* Handle any VRootAlias settings. */
@@ -373,10 +441,20 @@ static int handle_vroot_alias(void) {
*/
memset(src_path, '\0', sizeof(src_path));
- sstrncpy(src_path, c->argv[0], sizeof(src_path)-1);
+ ptr = c->argv[0];
+
+ /* Check for any expandable variables. */
+ ptr = path_subst_uservar(tmp_pool, &ptr);
+
+ sstrncpy(src_path, ptr, sizeof(src_path)-1);
vroot_clean_path(src_path);
- ptr = dir_best_path(tmp_pool, c->argv[1]);
+ ptr = c->argv[1];
+
+ /* Check for any expandable variables. */
+ ptr = path_subst_uservar(tmp_pool, &ptr);
+
+ ptr = dir_best_path(tmp_pool, ptr);
vroot_lookup_path(NULL, dst_path, sizeof(dst_path)-1, ptr,
VROOT_LOOKUP_FL_NO_ALIASES, NULL);
@@ -431,10 +509,9 @@ static int handle_vroot_alias(void) {
/* FS callbacks
*/
-static int vroot_stat(pr_fs_t *fs, const char *orig_path, struct stat *st) {
+static int vroot_stat(pr_fs_t *fs, const char *stat_path, struct stat *st) {
int res;
- char vpath[PR_TUNABLE_PATH_MAX + 1], *path;
- size_t path_len = 0;
+ char vpath[PR_TUNABLE_PATH_MAX + 1], *path = NULL;
pool *tmp_pool = NULL;
if (session.curr_phase == LOG_CMD ||
@@ -444,23 +521,11 @@ static int vroot_stat(pr_fs_t *fs, const char *orig_path, struct stat *st) {
/* NOTE: once stackable FS modules are supported, have this fall through
* to the next module in the stack.
*/
- return stat(orig_path, st);
+ return stat(stat_path, st);
}
tmp_pool = make_sub_pool(session.pool);
-
- path = pstrdup(tmp_pool, orig_path);
- vroot_clean_path(path);
-
- /* If the given path ends in a slash, remove it. The handling of
- * VRootAliases is sensitive to such things.
- */
- path_len = strlen(path);
- if (path_len > 1 &&
- path[path_len-1] == '/') {
- path[path_len-1] = '\0';
- path_len--;
- }
+ path = vroot_realpath(tmp_pool, stat_path, 0);
if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, path, 0, NULL) < 0) {
destroy_pool(tmp_pool);
@@ -474,8 +539,8 @@ static int vroot_stat(pr_fs_t *fs, const char *orig_path, struct stat *st) {
static int vroot_lstat(pr_fs_t *fs, const char *orig_path, struct stat *st) {
int res;
- char vpath[PR_TUNABLE_PATH_MAX + 1], *path;
- size_t path_len = 0;
+ char vpath[PR_TUNABLE_PATH_MAX + 1], *path = NULL;
+ size_t pathlen = 0;
pool *tmp_pool = NULL;
if (session.curr_phase == LOG_CMD ||
@@ -496,11 +561,11 @@ static int vroot_lstat(pr_fs_t *fs, const char *orig_path, struct stat *st) {
/* If the given path ends in a slash, remove it. The handling of
* VRootAliases is sensitive to such things.
*/
- path_len = strlen(path);
- if (path_len > 1 &&
- path[path_len-1] == '/') {
- path[path_len-1] = '\0';
- path_len--;
+ pathlen = strlen(path);
+ if (pathlen > 1 &&
+ path[pathlen-1] == '/') {
+ path[pathlen-1] = '\0';
+ pathlen--;
}
if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, path, 0, NULL) < 0) {
@@ -557,10 +622,7 @@ static int vroot_unlink(pr_fs_t *fs, const char *path) {
int res;
char vpath[PR_TUNABLE_PATH_MAX + 1];
- if (session.curr_phase == LOG_CMD ||
- session.curr_phase == LOG_CMD_ERR ||
- (session.sf_flags & SF_ABORT) ||
- *vroot_base == '\0') {
+ if (vroot_base[0] == '\0') {
/* NOTE: once stackable FS modules are supported, have this fall through
* to the next module in the stack.
*/
@@ -689,10 +751,11 @@ static int vroot_symlink(pr_fs_t *fs, const char *path1, const char *path2) {
return res;
}
-static int vroot_readlink(pr_fs_t *fs, const char *path, char *buf,
+static int vroot_readlink(pr_fs_t *fs, const char *readlink_path, char *buf,
size_t max) {
int res;
- char vpath[PR_TUNABLE_PATH_MAX + 1];
+ char vpath[PR_TUNABLE_PATH_MAX + 1], *path = NULL, *alias_path = NULL;
+ pool *tmp_pool = NULL;
if (session.curr_phase == LOG_CMD ||
session.curr_phase == LOG_CMD_ERR ||
@@ -701,13 +764,33 @@ static int vroot_readlink(pr_fs_t *fs, const char *path, char *buf,
/* NOTE: once stackable FS modules are supported, have this fall through
* to the next module in the stack.
*/
- return readlink(path, buf, max);
+ return readlink(readlink_path, buf, max);
}
- if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, path, 0, NULL) < 0)
+ /* In order to find any VRootAlias paths, we need to use the full path.
+ * However, if we do NOT find any VRootAlias, then we do NOT want to use
+ * the full path.
+ */
+
+ tmp_pool = make_sub_pool(session.pool);
+ path = vroot_realpath(tmp_pool, readlink_path, VROOT_REALPATH_FL_ABS_PATH);
+
+ if (vroot_lookup_path(tmp_pool, vpath, sizeof(vpath)-1, path, 0,
+ &alias_path) < 0) {
+ destroy_pool(tmp_pool);
return -1;
+ }
+
+ if (alias_path == NULL) {
+ if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, readlink_path, 0,
+ NULL) < 0) {
+ destroy_pool(tmp_pool);
+ return -1;
+ }
+ }
res = readlink(vpath, buf, max);
+ destroy_pool(tmp_pool);
return res;
}
@@ -777,6 +860,30 @@ static int vroot_chown(pr_fs_t *fs, const char *path, uid_t uid, gid_t gid) {
return res;
}
+#if PROFTPD_VERSION_NUMBER >= 0x0001030407
+static int vroot_lchown(pr_fs_t *fs, const char *path, uid_t uid, gid_t gid) {
+ int res;
+ char vpath[PR_TUNABLE_PATH_MAX + 1];
+
+ if (session.curr_phase == LOG_CMD ||
+ session.curr_phase == LOG_CMD_ERR ||
+ (session.sf_flags & SF_ABORT) ||
+ *vroot_base == '\0') {
+ /* NOTE: once stackable FS modules are supported, have this fall through
+ * to the next module in the stack.
+ */
+ res = lchown(path, uid, gid);
+ return res;
+ }
+
+ if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, path, 0, NULL) < 0)
+ return -1;
+
+ res = lchown(vpath, uid, gid);
+ return res;
+}
+#endif /* ProFTPD 1.3.4c or later */
+
static int vroot_chroot(pr_fs_t *fs, const char *path) {
char *chroot_path = "/", *tmp = NULL;
config_rec *c;
@@ -931,14 +1038,57 @@ static int vroot_chdir(pr_fs_t *fs, const char *path) {
return 0;
}
-static struct dirent vroot_dent;
+static int vroot_utimes(pr_fs_t *fs, const char *utimes_path,
+ struct timeval *tvs) {
+ int res;
+ char vpath[PR_TUNABLE_PATH_MAX + 1], *path = NULL;
+ pool *tmp_pool = NULL;
+
+ if (session.curr_phase == LOG_CMD ||
+ session.curr_phase == LOG_CMD_ERR ||
+ (session.sf_flags & SF_ABORT) ||
+ *vroot_base == '\0') {
+ /* NOTE: once stackable FS modules are supported, have this fall through
+ * to the next module in the stack.
+ */
+ res = utimes(utimes_path, tvs);
+ return res;
+ }
+
+ tmp_pool = make_sub_pool(session.pool);
+ path = vroot_realpath(tmp_pool, utimes_path, VROOT_REALPATH_FL_ABS_PATH);
+
+ if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, path, 0, NULL) < 0) {
+ destroy_pool(tmp_pool);
+ return -1;
+ }
+
+ res = utimes(vpath, tvs);
+ destroy_pool(tmp_pool);
+ return res;
+}
+
+static struct dirent *vroot_dent = NULL;
+static size_t vroot_dentsz = 0;
+
+/* On most systems, dirent.d_name is an array into which we can copy the
+ * name we want.
+ *
+ * However, on other systems (e.g. Solaris 2), dirent.d_name is an array size
+ * of 1. This approach makes use of the fact that the d_name member is the
+ * last member of the struct, meaning that the actual size is variable.
+ *
+ * We need to Do The Right Thing(tm) in either case.
+ */
+static size_t vroot_dent_namesz = 0;
+
static array_header *vroot_dir_aliases = NULL;
static int vroot_dir_idx = -1;
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, *dir_path, *real_path;
- char *ptr;
+ const char *alias_path = NULL, *dir_path = NULL, *real_path = NULL;
+ char *ptr = NULL;
alias_path = key_data;
real_path = value_data;
@@ -994,10 +1144,10 @@ static unsigned int vroot_dirtab_hash_cb(const void *key, size_t keysz) {
static void *vroot_opendir(pr_fs_t *fs, const char *orig_path) {
int res;
- char vpath[PR_TUNABLE_PATH_MAX + 1], *path;
- void *dirh;
+ char vpath[PR_TUNABLE_PATH_MAX + 1], *path = NULL;
+ void *dirh = NULL;
struct stat st;
- size_t path_len = 0;
+ size_t pathlen = 0;
pool *tmp_pool = NULL;
if (session.curr_phase == LOG_CMD ||
@@ -1022,11 +1172,11 @@ static void *vroot_opendir(pr_fs_t *fs, const char *orig_path) {
/* If the given path ends in a slash, remove it. The handling of
* VRootAliases is sensitive to such things.
*/
- path_len = strlen(path);
- if (path_len > 1 &&
- path[path_len-1] == '/') {
- path[path_len-1] = '\0';
- path_len--;
+ pathlen = strlen(path);
+ if (pathlen > 1 &&
+ path[pathlen-1] == '/') {
+ path[pathlen-1] = '\0';
+ pathlen--;
}
if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, path, 0, NULL) < 0) {
@@ -1127,7 +1277,7 @@ static void *vroot_opendir(pr_fs_t *fs, const char *orig_path) {
}
static struct dirent *vroot_readdir(pr_fs_t *fs, void *dirh) {
- struct dirent *dent;
+ struct dirent *dent = NULL;
next_dent:
dent = readdir((DIR *) dirh);
@@ -1165,11 +1315,18 @@ next_dent:
return NULL;
}
- memset(&vroot_dent, 0, sizeof(vroot_dent));
- sstrncpy(vroot_dent.d_name, elts[vroot_dir_idx++],
- sizeof(vroot_dent.d_name));
+ memset(vroot_dent, 0, vroot_dentsz);
- return &vroot_dent;
+ if (vroot_dent_namesz == 0) {
+ sstrncpy(vroot_dent->d_name, elts[vroot_dir_idx++],
+ sizeof(vroot_dent->d_name));
+
+ } else {
+ sstrncpy(vroot_dent->d_name, elts[vroot_dir_idx++],
+ vroot_dent_namesz);
+ }
+
+ return vroot_dent;
}
}
@@ -1390,6 +1547,90 @@ MODRET set_vrootserverroot(cmd_rec *cmd) {
/* Command handlers
*/
+MODRET vroot_log_retr(cmd_rec *cmd) {
+ const char *key;
+ char *path;
+
+ if (vroot_engine == FALSE ||
+ session.chroot_path == NULL) {
+ return PR_DECLINED(cmd);
+ }
+
+ key = "mod_xfer.retr-path";
+
+ path = pr_table_get(cmd->notes, key, NULL);
+ if (path != NULL) {
+ char *real_path;
+
+ if (*path == '/') {
+ real_path = pdircat(cmd->pool, vroot_base, path, NULL);
+ vroot_clean_path(real_path);
+
+ } else {
+ real_path = vroot_realpath(cmd->pool, path, VROOT_REALPATH_FL_ABS_PATH);
+ }
+
+ pr_table_set(cmd->notes, key, real_path, 0);
+ }
+
+ return PR_DECLINED(cmd);
+}
+
+MODRET vroot_log_stor(cmd_rec *cmd) {
+ const char *key;
+ char *path;
+
+ if (vroot_engine == FALSE ||
+ session.chroot_path == NULL) {
+ return PR_DECLINED(cmd);
+ }
+
+ key = "mod_xfer.store-path";
+
+ path = pr_table_get(cmd->notes, key, NULL);
+ if (path != NULL) {
+ char *real_path;
+
+ if (*path == '/') {
+ real_path = pdircat(cmd->pool, vroot_base, path, NULL);
+ vroot_clean_path(real_path);
+
+ } else {
+ real_path = vroot_realpath(cmd->pool, path, VROOT_REALPATH_FL_ABS_PATH);
+ }
+
+ pr_table_set(cmd->notes, key, real_path, 0);
+ }
+
+ return PR_DECLINED(cmd);
+}
+
+MODRET vroot_pre_mkd(cmd_rec *cmd) {
+ if (vroot_engine == FALSE ||
+ session.chroot_path == NULL) {
+ return PR_DECLINED(cmd);
+ }
+
+#if PROFTPD_VERSION_NUMBER >= 0x0001030407
+ vroot_use_mkdtemp = pr_fsio_set_use_mkdtemp(FALSE);
+#endif /* ProFTPD 1.3.4c or later */
+
+ return PR_DECLINED(cmd);
+}
+
+MODRET vroot_post_mkd(cmd_rec *cmd) {
+ if (vroot_engine == FALSE ||
+ session.chroot_path == NULL) {
+ return PR_DECLINED(cmd);
+ }
+
+#if PROFTPD_VERSION_NUMBER >= 0x0001030407
+ pr_fsio_set_use_mkdtemp(vroot_use_mkdtemp);
+#endif /* ProFTPD 1.3.4c or later */
+
+ return PR_DECLINED(cmd);
+}
+
MODRET vroot_pre_pass(cmd_rec *cmd) {
pr_fs_t *fs = NULL;
unsigned char *use_vroot = NULL;
@@ -1433,8 +1674,12 @@ MODRET vroot_pre_pass(cmd_rec *cmd) {
fs->truncate = vroot_truncate;
fs->chmod = vroot_chmod;
fs->chown = vroot_chown;
+#if PROFTPD_VERSION_NUMBER >= 0x0001030407
+ fs->lchown = vroot_lchown;
+#endif /* ProFTPD 1.3.4c or later */
fs->chdir = vroot_chdir;
fs->chroot = vroot_chroot;
+ fs->utimes = vroot_utimes;
fs->opendir = vroot_opendir;
fs->readdir = vroot_readdir;
fs->closedir = vroot_closedir;
@@ -1509,6 +1754,7 @@ MODRET vroot_post_pass_err(cmd_rec *cmd) {
static int vroot_sess_init(void) {
config_rec *c;
+ struct dirent dent;
c = find_config(main_server->conf, CONF_PARAM, "VRootLog", FALSE);
if (c) {
@@ -1545,6 +1791,18 @@ static int vroot_sess_init(void) {
}
}
+ /* Allocate the memory for the static struct dirent that we use, including
+ * determining the necessary sizes.
+ */
+ vroot_dentsz = sizeof(dent);
+ if (sizeof(dent.d_name) == 1) {
+ /* Allocate extra space for the dent path name. */
+ vroot_dent_namesz = PR_TUNABLE_PATH_MAX;
+ }
+
+ vroot_dentsz += vroot_dent_namesz;
+ vroot_dent = palloc(session.pool, vroot_dentsz);
+
return 0;
}
@@ -1564,6 +1822,34 @@ static cmdtable vroot_cmdtab[] = {
{ PRE_CMD, C_PASS, G_NONE, vroot_pre_pass, FALSE, FALSE },
{ POST_CMD, C_PASS, G_NONE, vroot_post_pass, FALSE, FALSE },
{ POST_CMD_ERR, C_PASS, G_NONE, vroot_post_pass_err, FALSE, FALSE },
+
+ { PRE_CMD, C_MKD, G_NONE, vroot_pre_mkd, FALSE, FALSE },
+ { POST_CMD, C_MKD, G_NONE, vroot_post_mkd, FALSE, FALSE },
+ { POST_CMD_ERR, C_MKD, G_NONE, vroot_post_mkd, FALSE, FALSE },
+ { PRE_CMD, C_XMKD, G_NONE, vroot_pre_mkd, FALSE, FALSE },
+ { POST_CMD, C_XMKD, G_NONE, vroot_post_mkd, FALSE, FALSE },
+ { POST_CMD_ERR, C_XMKD, G_NONE, vroot_post_mkd, FALSE, FALSE },
+
+ /* These command handlers are for manipulating cmd->notes, to get
+ * paths properly logged.
+ *
+ * Ideally these would be LOG_CMD/LOG_CMD_ERR phase handlers. HOWEVER,
+ * we need to transform things before the cmd is dispatched to mod_log,
+ * and mod_log uses a C_ANY handler for logging. And when dispatching,
+ * C_ANY handlers are run before named handlers. This means that using
+ * LOG_CMD/LOG_CMD_ERR handlers would be run AFTER mod_log's handler,
+ * even though we appear BEFORE mod_log in the module load order.
+ *
+ * Thus to do the transformation, we actually use POST_CMD/POST_CMD_ERR
+ * phase handlers here.
+ */
+ { POST_CMD, C_APPE, G_NONE, vroot_log_stor, FALSE, FALSE },
+ { POST_CMD_ERR, C_APPE, G_NONE, vroot_log_stor, FALSE, FALSE },
+ { POST_CMD, C_RETR, G_NONE, vroot_log_retr, FALSE, FALSE },
+ { POST_CMD_ERR, C_RETR, G_NONE, vroot_log_retr, FALSE, FALSE },
+ { POST_CMD, C_STOR, G_NONE, vroot_log_stor, FALSE, FALSE },
+ { POST_CMD_ERR, C_STOR, G_NONE, vroot_log_stor, FALSE, FALSE },
+
{ 0, NULL }
};
diff --git a/mod_vroot.html b/mod_vroot.html
index bb77699..f980f89 100644
--- a/mod_vroot.html
+++ b/mod_vroot.html
@@ -26,7 +26,7 @@ provides this capability by using ProFTPD's FS API, available as of 1.2.8rc1.
<p>
The most current version of <code>mod_vroot</code> can be found at:
<pre>
- <a href="http://www.castaglia.org/proftpd/">http://www.castaglia.org/proftpd/</a>
+ <a href="https://github.com/Castaglia/proftpd-mod_vroot.git">https://github.com/Castaglia/proftpd-mod_vroot.git</a>
</pre>
<h2>Author</h2>
@@ -79,6 +79,12 @@ This will automatically create an "upload" directory to appear in the
chroot area (in this case, the user's home directory).
<p>
+The <code>VRootAlias</code> directive is only needed for files/directories
+that are going to be accessed by remote clients. It is <b>not</b> needed
+for configuration files (<i>e.g.</i> PAM configuration files like <code>pam_env.conf</code>) needed by libraries. Using the <code>VRootAlias</code> for
+such library configuration files is pointless and wasteful.
+
+<p>
Note that this directive will <b>not</b> work if the
<code>VRootServerRoot</code> is used.
@@ -201,7 +207,7 @@ Last Updated: <i>$Date: 2009/10/19 16:30:18 $</i><br>
<hr>
<font size=2><b><i>
-© Copyright 2000-2009 TJ Saunders<br>
+© Copyright 2000-2013 TJ Saunders<br>
All Rights Reserved<br>
</i></b></font>
diff --git a/t/lib/ProFTPD/Tests/Modules/mod_vroot.pm b/t/lib/ProFTPD/Tests/Modules/mod_vroot.pm
index da96c66..010070b 100644
--- a/t/lib/ProFTPD/Tests/Modules/mod_vroot.pm
+++ b/t/lib/ProFTPD/Tests/Modules/mod_vroot.pm
@@ -64,11 +64,21 @@ my $TESTS = {
test_class => [qw(forking)],
},
+ vroot_dir_mkd => {
+ order => ++$order,
+ test_class => [qw(forking)],
+ },
+
vroot_server_root => {
order => ++$order,
test_class => [qw(forking rootprivs)],
},
+ vroot_server_root_mkd => {
+ order => ++$order,
+ test_class => [qw(bug forking rootprivs)],
+ },
+
vroot_alias_file_list => {
order => ++$order,
test_class => [qw(forking)],
@@ -149,6 +159,11 @@ my $TESTS = {
test_class => [qw(forking)],
},
+ vroot_alias_dir_cwd_stor => {
+ order => ++$order,
+ test_class => [qw(forking)],
+ },
+
vroot_alias_dir_cwd_cdup => {
order => ++$order,
test_class => [qw(forking)],
@@ -229,89 +244,88 @@ my $TESTS = {
test_class => [qw(forking mod_ifsession)],
},
- vroot_alias_ifclass => {
+ vroot_alias_ifgroup_list_stor => {
order => ++$order,
test_class => [qw(forking mod_ifsession)],
},
- vroot_alias_file_sftp_read => {
- order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
- },
-
- vroot_alias_file_sftp_write_no_overwrite => {
- order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
- },
-
- vroot_alias_file_sftp_write => {
- order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
- },
-
- vroot_alias_file_sftp_stat => {
- order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
- },
-
- vroot_alias_file_sftp_lstat => {
+ vroot_alias_ifclass => {
order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
+ test_class => [qw(forking mod_ifsession)],
},
- vroot_alias_file_sftp_realpath => {
+ vroot_showsymlinks_on => {
order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
+ test_class => [qw(bug forking)],
},
- vroot_alias_file_sftp_remove => {
+ vroot_hiddenstores_on_double_dot => {
order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
+ test_class => [qw(bug forking)],
},
- vroot_alias_dir_sftp_readdir => {
+ vroot_mfmt => {
order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
+ test_class => [qw(bug forking)],
},
- vroot_alias_dir_sftp_rmdir => {
+ vroot_log_extlog_retr => {
order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
+ test_class => [qw(forking)],
},
- vroot_alias_symlink_sftp_stat => {
+ vroot_log_extlog_stor => {
order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
+ test_class => [qw(forking)],
},
- vroot_alias_symlink_sftp_lstat => {
+ # XXX Currently does not work, since TransferLog logging can't be filtered
+# vroot_log_xferlog_retr => {
+# order => ++$order,
+# test_class => [qw(inprogress forking)],
+# },
+
+ # XXX Currently does not work, since TransferLog logging can't be filtered
+# vroot_log_xferlog_stor => {
+# order => ++$order,
+# test_class => [qw(inprogress forking)],
+# },
+
+ # XXX Currently does not work due to <Directory> matching logic, and to
+ # mod_vroot's session.chroot_path machinations.
+# vroot_config_limit_write => {
+# order => ++$order,
+# test_class => [qw(bug forking)],
+# },
+
+ vroot_config_deleteabortedstores_conn_aborted => {
order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
+ test_class => [qw(bug forking)],
},
- vroot_alias_symlink_sftp_realpath => {
+ vroot_config_deleteabortedstores_cmd_aborted => {
order => ++$order,
- test_class => [qw(forking mod_sftp sftp)],
+ test_class => [qw(bug forking)],
},
- vroot_alias_file_scp_download => {
+ vroot_alias_var_u_file => {
order => ++$order,
- test_class => [qw(forking mod_sftp scp)],
+ test_class => [qw(forking)],
},
- vroot_alias_file_scp_upload => {
+ vroot_alias_var_u_dir => {
order => ++$order,
- test_class => [qw(forking mod_sftp scp)],
+ test_class => [qw(forking)],
},
- vroot_showsymlinks_on => {
+ vroot_alias_var_u_dir_with_stor_mff => {
order => ++$order,
- test_class => [qw(bug forking)],
+ test_class => [qw(forking)],
},
- vroot_hiddenstores_on_double_dot => {
+ vroot_alias_var_u_symlink_dir => {
order => ++$order,
- test_class => [qw(bug forking)],
+ test_class => [qw(forking)],
},
};
@@ -330,21 +344,6 @@ sub list_tests {
# alias but not traversal?
}
-sub set_up {
- my $self = shift;
- $self->SUPER::set_up(@_);
-
- # Make sure that mod_sftp does not complain about permissions on the hostkey
- # files.
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
-
- unless (chmod(0400, $rsa_host_key, $dsa_host_key)) {
- die("Can't set perms on $rsa_host_key, $dsa_host_key: $!");
- }
-}
-
sub vroot_engine {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -353,13 +352,14 @@ sub vroot_engine {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -378,7 +378,7 @@ sub vroot_engine {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $config = {
PidFile => $pid_file,
@@ -419,7 +419,6 @@ sub vroot_engine {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -443,7 +442,7 @@ sub vroot_engine {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -510,7 +509,7 @@ sub vroot_engine {
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -575,7 +574,7 @@ sub vroot_engine {
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -640,6 +639,9 @@ sub vroot_engine {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -654,7 +656,7 @@ sub vroot_anon {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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");
@@ -756,7 +758,7 @@ EOC
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -823,7 +825,7 @@ EOC
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -888,7 +890,7 @@ EOC
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -953,6 +955,9 @@ EOC
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -967,13 +972,14 @@ sub vroot_symlink {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
my $uid = 500;
my $gid = 500;
@@ -994,7 +1000,7 @@ sub vroot_symlink {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
# Create a symlink to a file that is outside of the vroot
my $test_file = File::Spec->rel2abs("$tmpdir/bar.txt");
@@ -1063,7 +1069,6 @@ sub vroot_symlink {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my $conn = $client->list_raw();
@@ -1073,7 +1078,7 @@ sub vroot_symlink {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -1133,6 +1138,9 @@ sub vroot_symlink {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -1147,13 +1155,14 @@ sub vroot_symlink_eloop {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
my $uid = 500;
my $gid = 500;
@@ -1174,7 +1183,7 @@ sub vroot_symlink_eloop {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
# Create a symlink to a file that is outside of the vroot
my $test_file = File::Spec->rel2abs("$tmpdir/test.txt");
@@ -1243,7 +1252,6 @@ sub vroot_symlink_eloop {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my $conn = $client->list_raw();
@@ -1253,7 +1261,7 @@ sub vroot_symlink_eloop {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -1316,6 +1324,9 @@ sub vroot_symlink_eloop {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -1330,13 +1341,14 @@ sub vroot_opt_allow_symlinks_file {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
my $uid = 500;
my $gid = 500;
@@ -1357,7 +1369,7 @@ sub vroot_opt_allow_symlinks_file {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
# Create a symlink to a file that is outside of the vroot
my $test_file = File::Spec->rel2abs("$tmpdir/bar.txt");
@@ -1428,7 +1440,6 @@ sub vroot_opt_allow_symlinks_file {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my $conn = $client->list_raw();
@@ -1438,7 +1449,7 @@ sub vroot_opt_allow_symlinks_file {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -1480,19 +1491,12 @@ sub vroot_opt_allow_symlinks_file {
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
my $resp_code = $client->response_code();
my $resp_msg = $client->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client->quit();
};
@@ -1520,6 +1524,9 @@ sub vroot_opt_allow_symlinks_file {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -1534,13 +1541,14 @@ sub vroot_opt_allow_symlinks_dir_retr {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
my $uid = 500;
my $gid = 500;
@@ -1564,7 +1572,7 @@ sub vroot_opt_allow_symlinks_dir_retr {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
# Create a symlink to a directory that is outside of the vroot
my $test_file = File::Spec->rel2abs("$public_dir/test.txt");
@@ -1635,7 +1643,6 @@ sub vroot_opt_allow_symlinks_dir_retr {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my $conn = $client->list_raw();
@@ -1645,7 +1652,7 @@ sub vroot_opt_allow_symlinks_dir_retr {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -1687,19 +1694,12 @@ sub vroot_opt_allow_symlinks_dir_retr {
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
my $resp_code = $client->response_code();
my $resp_msg = $client->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client->quit();
};
@@ -1727,6 +1727,9 @@ sub vroot_opt_allow_symlinks_dir_retr {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -1741,13 +1744,14 @@ sub vroot_opt_allow_symlinks_dir_stor_no_overwrite {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
my $uid = 500;
my $gid = 500;
@@ -1771,7 +1775,7 @@ sub vroot_opt_allow_symlinks_dir_stor_no_overwrite {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
# Create a symlink to a directory that is outside of the vroot
my $test_file = File::Spec->rel2abs("$public_dir/test.txt");
@@ -1842,7 +1846,6 @@ sub vroot_opt_allow_symlinks_dir_stor_no_overwrite {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my $conn = $client->list_raw();
@@ -1852,7 +1855,7 @@ sub vroot_opt_allow_symlinks_dir_stor_no_overwrite {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -1930,6 +1933,9 @@ sub vroot_opt_allow_symlinks_dir_stor_no_overwrite {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -1944,13 +1950,14 @@ sub vroot_opt_allow_symlinks_dir_stor {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
my $uid = 500;
my $gid = 500;
@@ -1974,7 +1981,7 @@ sub vroot_opt_allow_symlinks_dir_stor {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
# Create a symlink to a directory that is outside of the vroot
my $test_file = File::Spec->rel2abs("$public_dir/test.txt");
@@ -2046,7 +2053,6 @@ sub vroot_opt_allow_symlinks_dir_stor {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my $conn = $client->list_raw();
@@ -2056,7 +2062,7 @@ sub vroot_opt_allow_symlinks_dir_stor {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -2099,19 +2105,12 @@ sub vroot_opt_allow_symlinks_dir_stor {
}
my $buf = "Farewell cruel world!";
- $conn->write($buf, length($buf), 30);
+ $conn->write($buf, length($buf), 25);
eval { $conn->close() };
my $resp_code = $client->response_code();
my $resp_msg = $client->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client->quit();
};
@@ -2139,6 +2138,9 @@ sub vroot_opt_allow_symlinks_dir_stor {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -2153,13 +2155,14 @@ sub vroot_opt_allow_symlinks_dir_cwd {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
my $uid = 500;
my $gid = 500;
@@ -2183,7 +2186,7 @@ sub vroot_opt_allow_symlinks_dir_cwd {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
# Create a symlink to a directory that is outside of the vroot
my $test_file = File::Spec->rel2abs("$public_dir/test.txt");
@@ -2254,7 +2257,6 @@ sub vroot_opt_allow_symlinks_dir_cwd {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my $conn = $client->list_raw();
@@ -2264,7 +2266,7 @@ sub vroot_opt_allow_symlinks_dir_cwd {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -2317,7 +2319,7 @@ sub vroot_opt_allow_symlinks_dir_cwd {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -2409,6 +2411,195 @@ sub vroot_opt_allow_symlinks_dir_cwd {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_dir_mkd {
+ 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);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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 $sub_dir = File::Spec->rel2abs("$tmpdir/foo.d");
+ mkpath($sub_dir);
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10 vroot:20',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ Directory => {
+ # BUG: This should be $sub_dir. But due to how mod_vroot currently
+ # works, the <Directory> path has to be modified to match the
+ # mod_vroot. (I.e. for the purposes of this test, just '/foo.d').
+ # Sigh.
+
+ # '/foo.d' => {
+ $sub_dir => {
+ # Test the UserOwner directive in the <Directory> setting
+ UserOwner => 'root',
+ },
+ },
+
+ IfModules => {
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+ },
+
+ '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);
+ $client->cwd('foo.d');
+ $client->mkd('bar.d');
+
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+
+ my $expected;
+
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected response code $expected, got $resp_code"));
+
+ $expected = "\"/foo.d/bar.d\" - Directory successfully created";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected response message '$expected', got '$resp_msg'"));
+
+ $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);
+
+ eval {
+ if (open(my $fh, "< $log_file")) {
+ # Look for the 'smkdir' fsio channel trace message; it will tell us
+ # whether the UserOwner directive from the <Directory> section was
+ # successfully found.
+
+ my $have_smkdir_line = 0;
+ my $line;
+ while ($line = <$fh>) {
+ chomp($line);
+
+ if ($line =~ /smkdir/) {
+ $have_smkdir_line = 1;
+ last;
+ }
+ }
+
+ close($fh);
+
+ $self->assert($have_smkdir_line,
+ test_msg("Did not find expected 'fsio' channel TraceLog line in $log_file"));
+
+ if ($line =~ /UID (\d+)/) {
+ my $smkdir_uid = $1;
+
+ if ($< == 0) {
+ $self->assert($smkdir_uid == 0,
+ test_msg("Expected UID 0, got $smkdir_uid"));
+ }
+
+ } else {
+ die("Unexpectedly formatted 'fsio' channel TraceLog line '$line'");
+ }
+
+ } else {
+ die("Can't read $log_file: $!");
+ }
+ };
+ if ($@) {
+ $ex = $@;
+ }
+
+ if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -2423,13 +2614,14 @@ sub vroot_server_root {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
my $uid = 500;
my $gid = 500;
@@ -2452,7 +2644,7 @@ sub vroot_server_root {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $config = {
PidFile => $pid_file,
@@ -2496,7 +2688,6 @@ sub vroot_server_root {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -2520,7 +2711,7 @@ sub vroot_server_root {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -2564,7 +2755,7 @@ sub vroot_server_root {
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -2607,7 +2798,7 @@ sub vroot_server_root {
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -2649,13 +2840,16 @@ sub vroot_server_root {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_file_list {
+sub vroot_server_root_mkd {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -2663,13 +2857,173 @@ sub vroot_alias_file_list {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/home");
+ my $uid = 500;
+ my $gid = 500;
+
+ mkpath($home_dir);
+
+ my $abs_tmpdir = File::Spec->rel2abs($tmpdir);
+
+ my $test_dir = File::Spec->rel2abs("$home_dir/test.d");
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ VRootServerRoot => $abs_tmpdir,
+ DefaultRoot => '~',
+ },
+
+ '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'"));
+
+ ($resp_code, $resp_msg) = $client->mkd('test.d');
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "\"/test.d\" - Directory successfully created";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ ($resp_code, $resp_msg) = $client->cwd('test.d');
+ $expected = 250;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = 'CWD command successful';
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ ($resp_code, $resp_msg) = $client->pwd();
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "\"/test.d\" is the current directory";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ $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_file_list {
+ 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);
my $uid = 500;
my $gid = 500;
@@ -2688,7 +3042,7 @@ sub vroot_alias_file_list {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -2746,7 +3100,6 @@ sub vroot_alias_file_list {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -2770,7 +3123,7 @@ sub vroot_alias_file_list {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -2837,6 +3190,9 @@ sub vroot_alias_file_list {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -2851,13 +3207,14 @@ sub vroot_alias_file_list_multi {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -2876,7 +3233,7 @@ sub vroot_alias_file_list_multi {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -2937,7 +3294,6 @@ sub vroot_alias_file_list_multi {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -2961,7 +3317,7 @@ sub vroot_alias_file_list_multi {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -3029,6 +3385,9 @@ sub vroot_alias_file_list_multi {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -3043,13 +3402,14 @@ sub vroot_alias_file_retr {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -3068,9 +3428,12 @@ sub vroot_alias_file_retr {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ my $test_dir = File::Spec->rel2abs("$tmpdir/test.d");
+ mkpath($test_dir);
+
+ my $src_file = File::Spec->rel2abs("$test_dir/foo.txt");
if (open(my $fh, "> $src_file")) {
print $fh "Hello, World!\n";
unless (close($fh)) {
@@ -3088,7 +3451,7 @@ sub vroot_alias_file_retr {
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,
@@ -3136,25 +3499,16 @@ sub vroot_alias_file_retr {
}
my $buf;
- my $count = $conn->read($buf, 8192, 30);
+ my $count = $conn->read($buf, 8192, 5);
eval { $conn->close() };
my $resp_code = $client->response_code();
my $resp_msg = $client->response_msg();
-
- my $expected;
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = 'Transfer complete';
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client->quit();
- $expected = 14;
+ my $expected = 14;
$self->assert($expected == $count,
test_msg("Expected $expected, got $count"));
};
@@ -3181,6 +3535,9 @@ sub vroot_alias_file_retr {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -3195,13 +3552,14 @@ sub vroot_alias_file_stor_no_overwrite {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -3220,7 +3578,7 @@ sub vroot_alias_file_stor_no_overwrite {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -3324,6 +3682,9 @@ sub vroot_alias_file_stor_no_overwrite {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -3338,13 +3699,14 @@ sub vroot_alias_file_stor {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -3363,7 +3725,7 @@ sub vroot_alias_file_stor {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -3433,21 +3795,12 @@ sub vroot_alias_file_stor {
}
my $buf = "Farewell, cruel world";
- $conn->write($buf, length($buf), 30);
+ $conn->write($buf, length($buf), 25);
eval { $conn->close() };
my $resp_code = $client->response_code();
my $resp_msg = $client->response_msg();
-
- my $expected;
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = 'Transfer complete';
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client->quit();
};
@@ -3474,6 +3827,9 @@ sub vroot_alias_file_stor {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -3488,13 +3844,14 @@ sub vroot_alias_file_dele {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -3513,7 +3870,7 @@ sub vroot_alias_file_dele {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -3617,6 +3974,9 @@ sub vroot_alias_file_dele {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -3631,13 +3991,14 @@ sub vroot_alias_file_mlsd {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -3656,7 +4017,7 @@ sub vroot_alias_file_mlsd {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -3759,6 +4120,9 @@ sub vroot_alias_file_mlsd {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -3773,13 +4137,14 @@ sub vroot_alias_file_mlst {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -3798,7 +4163,7 @@ sub vroot_alias_file_mlst {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -3895,6 +4260,9 @@ sub vroot_alias_file_mlst {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -3909,13 +4277,14 @@ sub vroot_alias_dup_same_name {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -3934,7 +4303,7 @@ sub vroot_alias_dup_same_name {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -3992,7 +4361,6 @@ sub vroot_alias_dup_same_name {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -4016,7 +4384,7 @@ sub vroot_alias_dup_same_name {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -4082,6 +4450,9 @@ sub vroot_alias_dup_same_name {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -4096,13 +4467,14 @@ sub vroot_alias_dup_colliding_aliases {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -4121,7 +4493,7 @@ sub vroot_alias_dup_colliding_aliases {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -4180,7 +4552,6 @@ sub vroot_alias_dup_colliding_aliases {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -4204,7 +4575,7 @@ sub vroot_alias_dup_colliding_aliases {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -4271,6 +4642,9 @@ sub vroot_alias_dup_colliding_aliases {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -4285,13 +4659,14 @@ sub vroot_alias_delete_source {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -4310,7 +4685,7 @@ sub vroot_alias_delete_source {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -4368,7 +4743,6 @@ sub vroot_alias_delete_source {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -4405,7 +4779,7 @@ sub vroot_alias_delete_source {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -4470,6 +4844,9 @@ sub vroot_alias_delete_source {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -4484,13 +4861,14 @@ sub vroot_alias_no_source {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -4509,7 +4887,7 @@ sub vroot_alias_no_source {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
my $dst_file = '~/bar.txt';
@@ -4557,7 +4935,6 @@ sub vroot_alias_no_source {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -4581,7 +4958,7 @@ sub vroot_alias_no_source {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -4646,6 +5023,9 @@ sub vroot_alias_no_source {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -4660,13 +5040,14 @@ sub vroot_alias_dir_list_no_trailing_slash {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -4685,7 +5066,7 @@ sub vroot_alias_dir_list_no_trailing_slash {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -4735,7 +5116,6 @@ sub vroot_alias_dir_list_no_trailing_slash {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -4759,7 +5139,7 @@ sub vroot_alias_dir_list_no_trailing_slash {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -4826,6 +5206,9 @@ sub vroot_alias_dir_list_no_trailing_slash {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -4840,13 +5223,14 @@ sub vroot_alias_dir_list_with_trailing_slash {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -4865,7 +5249,7 @@ sub vroot_alias_dir_list_with_trailing_slash {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -4915,7 +5299,6 @@ sub vroot_alias_dir_list_with_trailing_slash {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -4939,7 +5322,7 @@ sub vroot_alias_dir_list_with_trailing_slash {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -5006,6 +5389,9 @@ sub vroot_alias_dir_list_with_trailing_slash {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -5020,13 +5406,14 @@ sub vroot_alias_dir_list_from_above {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -5045,7 +5432,7 @@ sub vroot_alias_dir_list_from_above {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -5119,7 +5506,6 @@ sub vroot_alias_dir_list_from_above {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -5142,7 +5528,7 @@ sub vroot_alias_dir_list_from_above {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -5204,6 +5590,9 @@ sub vroot_alias_dir_list_from_above {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -5218,13 +5607,14 @@ sub vroot_alias_dir_cwd_list {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -5243,7 +5633,7 @@ sub vroot_alias_dir_cwd_list {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -5317,7 +5707,6 @@ sub vroot_alias_dir_cwd_list {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -5360,7 +5749,7 @@ sub vroot_alias_dir_cwd_list {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -5422,13 +5811,16 @@ sub vroot_alias_dir_cwd_list {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_dir_cwd_cdup {
+sub vroot_alias_dir_cwd_stor {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -5436,13 +5828,14 @@ sub vroot_alias_dir_cwd_cdup {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -5461,9 +5854,9 @@ sub vroot_alias_dir_cwd_cdup {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
- my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
+ my $src_dir = File::Spec->rel2abs("$tmpdir/sub1.d/sub2.d/foo.d");
mkpath($src_dir);
my $dst_dir = '~/bar.d';
@@ -5473,7 +5866,7 @@ sub vroot_alias_dir_cwd_cdup {
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,
@@ -5511,7 +5904,6 @@ sub vroot_alias_dir_cwd_cdup {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -5547,8 +5939,175 @@ sub vroot_alias_dir_cwd_cdup {
$self->assert($expected eq $resp_msg,
test_msg("Expected '$expected', got '$resp_msg'"));
- ($resp_code, $resp_msg) = $client->cdup();
-
+ my $conn = $client->stor_raw('test.txt');
+ unless ($conn) {
+ die("Failed to STOR: " . $client->response_code() . " " .
+ $client->response_msg());
+ }
+
+ my $buf = "Hello, World!";
+ $conn->write($buf, length($buf), 5);
+ 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();
+ };
+
+ 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_dir_cwd_cdup {
+ 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);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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 $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
+ mkpath($src_dir);
+
+ my $dst_dir = '~/bar.d';
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10 vroot:20',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_dir $dst_dir",
+ },
+
+ '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);
+ ($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'"));
+
+ ($resp_code, $resp_msg) = $client->cwd('bar.d');
+
+ $expected = 250;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "CWD command successful";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ ($resp_code, $resp_msg) = $client->pwd();
+
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "\"/bar.d\" is the current directory";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ ($resp_code, $resp_msg) = $client->cdup();
+
$expected = 250;
$self->assert($expected == $resp_code,
test_msg("Expected $expected, got $resp_code"));
@@ -5592,6 +6151,9 @@ sub vroot_alias_dir_cwd_cdup {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -5606,13 +6168,14 @@ sub vroot_alias_dir_mkd {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -5631,7 +6194,7 @@ sub vroot_alias_dir_mkd {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -5643,7 +6206,7 @@ sub vroot_alias_dir_mkd {
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,
@@ -5726,6 +6289,9 @@ sub vroot_alias_dir_mkd {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -5740,13 +6306,14 @@ sub vroot_alias_dir_rmd {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -5765,7 +6332,7 @@ sub vroot_alias_dir_rmd {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -5860,6 +6427,9 @@ sub vroot_alias_dir_rmd {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -5874,13 +6444,14 @@ sub vroot_alias_dir_cwd_mlsd {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -5899,7 +6470,7 @@ sub vroot_alias_dir_cwd_mlsd {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -5993,7 +6564,7 @@ sub vroot_alias_dir_cwd_mlsd {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -6057,6 +6628,9 @@ sub vroot_alias_dir_cwd_mlsd {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -6071,13 +6645,14 @@ sub vroot_alias_dir_mlsd_from_above {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -6096,7 +6671,7 @@ sub vroot_alias_dir_mlsd_from_above {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -6179,7 +6754,7 @@ sub vroot_alias_dir_mlsd_from_above {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -6243,6 +6818,9 @@ sub vroot_alias_dir_mlsd_from_above {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -6257,13 +6835,14 @@ sub vroot_alias_dir_outside_root_cwd_mlsd {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/baz");
mkpath($home_dir);
my $uid = 500;
@@ -6283,7 +6862,7 @@ sub vroot_alias_dir_outside_root_cwd_mlsd {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -6377,7 +6956,7 @@ sub vroot_alias_dir_outside_root_cwd_mlsd {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -6441,6 +7020,9 @@ sub vroot_alias_dir_outside_root_cwd_mlsd {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -6455,13 +7037,14 @@ sub vroot_alias_dir_outside_root_cwd_mlsd_cwd_ls {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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/baz");
mkpath($home_dir);
my $uid = 500;
@@ -6481,7 +7064,7 @@ sub vroot_alias_dir_outside_root_cwd_mlsd_cwd_ls {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -6589,7 +7172,7 @@ sub vroot_alias_dir_outside_root_cwd_mlsd_cwd_ls {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -6646,7 +7229,7 @@ sub vroot_alias_dir_outside_root_cwd_mlsd_cwd_ls {
}
$buf = '';
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -6716,6 +7299,9 @@ sub vroot_alias_dir_outside_root_cwd_mlsd_cwd_ls {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -6730,13 +7316,14 @@ sub vroot_alias_dir_mlst {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -6755,7 +7342,7 @@ sub vroot_alias_dir_mlst {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
mkpath($src_dir);
@@ -6844,6 +7431,9 @@ sub vroot_alias_dir_mlst {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -6858,13 +7448,14 @@ sub vroot_alias_symlink_list {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -6883,7 +7474,7 @@ sub vroot_alias_symlink_list {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -6957,7 +7548,6 @@ sub vroot_alias_symlink_list {
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -6981,7 +7571,7 @@ sub vroot_alias_symlink_list {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -7049,6 +7639,9 @@ sub vroot_alias_symlink_list {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -7063,13 +7656,14 @@ sub vroot_alias_symlink_retr {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -7088,7 +7682,7 @@ sub vroot_alias_symlink_retr {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -7172,25 +7766,16 @@ sub vroot_alias_symlink_retr {
}
my $buf;
- my $count = $conn->read($buf, 8192, 30);
+ my $count = $conn->read($buf, 8192, 5);
eval { $conn->close() };
my $resp_code = $client->response_code();
my $resp_msg = $client->response_msg();
-
- my $expected;
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = 'Transfer complete';
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client->quit();
- $expected = 14;
+ my $expected = 14;
$self->assert($expected == $count,
test_msg("Expected $expected, got $count"));
};
@@ -7217,6 +7802,9 @@ sub vroot_alias_symlink_retr {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -7231,13 +7819,14 @@ sub vroot_alias_symlink_stor_no_overwrite {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -7256,7 +7845,7 @@ sub vroot_alias_symlink_stor_no_overwrite {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -7376,6 +7965,9 @@ sub vroot_alias_symlink_stor_no_overwrite {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -7390,13 +7982,14 @@ sub vroot_alias_symlink_stor {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -7415,7 +8008,7 @@ sub vroot_alias_symlink_stor {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -7501,21 +8094,12 @@ sub vroot_alias_symlink_stor {
}
my $buf = "Farewell, cruel world";
- $conn->write($buf, length($buf), 30);
+ $conn->write($buf, length($buf), 25);
eval { $conn->close() };
my $resp_code = $client->response_code();
my $resp_msg = $client->response_msg();
-
- my $expected;
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = 'Transfer complete';
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client->quit();
};
@@ -7542,6 +8126,9 @@ sub vroot_alias_symlink_stor {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -7556,13 +8143,14 @@ sub vroot_alias_symlink_mlsd {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -7581,7 +8169,7 @@ sub vroot_alias_symlink_mlsd {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -7700,6 +8288,9 @@ sub vroot_alias_symlink_mlsd {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -7714,13 +8305,14 @@ sub vroot_alias_symlink_mlst {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -7739,7 +8331,7 @@ sub vroot_alias_symlink_mlst {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -7852,6 +8444,9 @@ sub vroot_alias_symlink_mlst {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -7866,13 +8461,14 @@ sub vroot_alias_ifuser {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -7891,7 +8487,7 @@ sub vroot_alias_ifuser {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -7966,7 +8562,6 @@ EOC
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
@@ -7990,7 +8585,7 @@ EOC
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -8057,6 +8652,9 @@ EOC
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
@@ -8071,7 +8669,7 @@ sub vroot_alias_ifgroup {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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");
@@ -8142,11 +8740,11 @@ sub vroot_alias_ifgroup {
print $fh <<EOC;
<IfGroup $group>
VRootAlias $src_file $dst_file1
-</IfUser>
+</IfGroup>
<IfGroup !$group>
VRootAlias $src_file $dst_file2
-</IfUser>
+</IfGroup>
EOC
unless (close($fh)) {
die("Can't write $config_file: $!");
@@ -8172,11 +8770,9 @@ EOC
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
-
($resp_code, $resp_msg) = $client->pwd();
my $expected;
@@ -8196,7 +8792,7 @@ EOC
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
# We have to be careful of the fact that readdir returns directory
@@ -8263,13 +8859,16 @@ EOC
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_ifclass {
+sub vroot_alias_ifgroup_list_stor {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -8277,7 +8876,7 @@ sub vroot_alias_ifclass {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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");
@@ -8285,18 +8884,22 @@ sub vroot_alias_ifclass {
my $user = 'proftpd';
my $passwd = 'test';
my $group = 'ftpd';
- my $home_dir = File::Spec->rel2abs($tmpdir);
+ my $home_dir = File::Spec->rel2abs("$tmpdir/home/$user");
+ mkpath($home_dir);
my $uid = 500;
my $gid = 500;
+ my $shared_dir = File::Spec->rel2abs("$tmpdir/shared");
+ mkpath($shared_dir);
+
# 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)) {
+ unless (chmod(0755, $home_dir, $shared_dir)) {
die("Can't set perms on $home_dir to 0755: $!");
}
- unless (chown($uid, $gid, $home_dir)) {
+ unless (chown($uid, $gid, $home_dir, $shared_dir)) {
die("Can't set owner of $home_dir to $uid/$gid: $!");
}
}
@@ -8305,20 +8908,17 @@ sub vroot_alias_ifclass {
'/bin/bash');
auth_group_write($auth_group_file, $group, $gid, $user);
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
+ my $test_file = File::Spec->rel2abs("$shared_dir/test.txt");
+ if (open(my $fh, "> $test_file")) {
print $fh "Hello, World!\n";
unless (close($fh)) {
- die("Can't write $src_file: $!");
+ die("Can't write $test_file: $!");
}
} else {
- die("Can't open $src_file: $!");
+ die("Can't open $test_file: $!");
}
- my $dst_file1 = '~/bar.txt';
- my $dst_file2 = '~/baz.txt';
-
my $config = {
PidFile => $pid_file,
ScoreboardFile => $scoreboard_file,
@@ -8346,17 +8946,9 @@ sub vroot_alias_ifclass {
if (open(my $fh, ">> $config_file")) {
print $fh <<EOC;
-<Class test>
- From 127.0.0.1
-</Class>
-
-<IfClass test>
- VRootAlias $src_file $dst_file1
-</IfUser>
-
-<IfClass !test>
- VRootAlias $src_file $dst_file2
-</IfUser>
+<IfGroup $group>
+ VRootAlias $shared_dir ~/shared
+</IfGroup>
EOC
unless (close($fh)) {
die("Can't write $config_file: $!");
@@ -8382,11 +8974,9 @@ EOC
if ($pid) {
eval {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-
$client->login($user, $passwd);
my ($resp_code, $resp_msg);
-
($resp_code, $resp_msg) = $client->pwd();
my $expected;
@@ -8406,9 +8996,13 @@ EOC
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
+ $resp_code = $client->response_code();
+ $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
+
# We have to be careful of the fact that readdir returns directory
# entries in an unordered fashion.
my $res = {};
@@ -8430,8 +9024,7 @@ EOC
'vroot.pid' => 1,
'vroot.scoreboard' => 1,
'vroot.scoreboard.lck' => 1,
- 'foo.txt' => 1,
- 'bar.txt' => 1,
+ 'shared' => 1,
};
my $ok = 1;
@@ -8444,10 +9037,80 @@ EOC
}
}
- unless ($ok) {
- die("Unexpected name '$mismatch' appeared in LIST data")
+ $self->assert($ok,
+ test_msg("Unexpected name '$mismatch' appeared in LIST data"));
+
+ ($resp_code, $resp_msg) = $client->cwd('shared');
+
+ $expected = 250;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = 'CWD command successful';
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ $conn = $client->list_raw('-al');
+ unless ($conn) {
+ die("Failed to LIST: " . $client->response_code() . " " .
+ $client->response_msg());
+ }
+
+ $buf = '';
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
+
+ $resp_code = $client->response_code();
+ $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
+
+ # We have to be careful of the fact that readdir returns directory
+ # entries in an unordered fashion.
+ $res = {};
+ $lines = [split(/\n/, $buf)];
+ foreach my $line (@$lines) {
+ if ($line =~ /^\S+\s+\d+\s+\S+\s+\S+\s+.*?\s+(\S+)$/) {
+ $res->{$1} = 1;
+ }
+ }
+
+ unless (scalar(keys(%$res)) > 0) {
+ die("LIST data unexpectedly empty");
+ }
+
+ $expected = {
+ '.' => 1,
+ '..' => 1,
+ 'test.txt' => 1,
+ };
+
+ $ok = 1;
+ $mismatch = undef;
+ foreach my $name (keys(%$res)) {
+ unless (defined($expected->{$name})) {
+ $mismatch = $name;
+ $ok = 0;
+ last;
+ }
+ }
+
+ $self->assert($ok,
+ test_msg("Unexpected name '$mismatch' appeared in LIST data"));
+
+ $conn = $client->stor_raw('bar.txt');
+ unless ($conn) {
+ die("Failed to STOR bar.txt: " . $client->response_code() . " " .
+ $client->response_msg());
}
+ $buf = "Farewell, cruel world!\n";
+ $conn->write($buf, length($buf), 5);
+ eval { $conn->close() };
+
+ $resp_code = $client->response_code();
+ $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
+
$client->quit();
};
@@ -8473,13 +9136,16 @@ EOC
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_file_sftp_read {
+sub vroot_alias_ifclass {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -8487,13 +9153,14 @@ sub vroot_alias_file_sftp_read {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -8512,7 +9179,7 @@ sub vroot_alias_file_sftp_read {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
if (open(my $fh, "> $src_file")) {
@@ -8525,10 +9192,8 @@ sub vroot_alias_file_sftp_read {
die("Can't open $src_file: $!");
}
- my $dst_file = '~/bar.txt';
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ my $dst_file1 = '~/bar.txt';
+ my $dst_file2 = '~/baz.txt';
my $config = {
PidFile => $pid_file,
@@ -8541,19 +9206,10 @@ sub vroot_alias_file_sftp_read {
AuthGroupFile => $auth_group_file,
IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
-
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
DefaultRoot => '~',
-
- VRootAlias => "$src_file $dst_file",
},
'mod_delay.c' => {
@@ -8564,6 +9220,28 @@ sub vroot_alias_file_sftp_read {
my ($port, $config_user, $config_group) = config_write($config_file, $config);
+ if (open(my $fh, ">> $config_file")) {
+ print $fh <<EOC;
+<Class test>
+ From 127.0.0.1
+</Class>
+
+<IfClass test>
+ VRootAlias $src_file $dst_file1
+</IfClass>
+
+<IfClass !test>
+ VRootAlias $src_file $dst_file2
+</IfClass>
+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.
@@ -8572,62 +9250,79 @@ sub vroot_alias_file_sftp_read {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# Fork child
$self->handle_sigchld();
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
- my $ssh2 = Net::SSH2->new();
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- sleep(1);
+ my ($resp_code, $resp_msg);
+ ($resp_code, $resp_msg) = $client->pwd();
- 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");
- }
+ my $expected;
- unless ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ $expected = "\"/\" is the current directory";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
- my $fh = $sftp->open('bar.txt', O_RDONLY);
- unless ($fh) {
- my ($err_code, $err_name) = $sftp->error();
- die("Can't open bar.txt: [$err_name] ($err_code)");
+ my $conn = $client->list_raw();
+ unless ($conn) {
+ die("Failed to LIST: " . $client->response_code() . " " .
+ $client->response_msg());
}
my $buf;
- my $size = 0;
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
- my $res = $fh->read($buf, 8192, 30);
- while ($res) {
- $size += $res;
+ # 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->{$1} = 1;
+ }
+ }
- $res = $fh->read($buf, 8192, 30);
+ unless (scalar(keys(%$res)) > 0) {
+ die("LIST data unexpectedly empty");
}
- # To issue the FXP_CLOSE, we have to explicit destroy the filehandle
- $fh = undef;
+ my $expected = {
+ 'vroot.conf' => 1,
+ 'vroot.group' => 1,
+ 'vroot.passwd' => 1,
+ 'vroot.pid' => 1,
+ 'vroot.scoreboard' => 1,
+ 'vroot.scoreboard.lck' => 1,
+ 'foo.txt' => 1,
+ 'bar.txt' => 1,
+ };
- my $expected = 14;
- $self->assert($expected == $size,
- test_msg("Expected $expected, got $size"));
+ 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")
+ }
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -8652,13 +9347,16 @@ sub vroot_alias_file_sftp_read {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_file_sftp_write_no_overwrite {
+sub vroot_showsymlinks_on {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -8666,17 +9364,19 @@ sub vroot_alias_file_sftp_write_no_overwrite {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $home_dir = File::Spec->rel2abs("$tmpdir/home");
my $uid = 500;
my $gid = 500;
+ mkpath($home_dir);
+
# Make sure that, if we're running as root, that the home directory has
# permissions/privs set for the account we create
if ($< == 0) {
@@ -8693,21 +9393,61 @@ sub vroot_alias_file_sftp_write_no_overwrite {
'/bin/bash');
auth_group_write($auth_group_file, 'ftpd', $gid, $user);
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
+ # See:
+ #
+ # http://forums.proftpd.org/smf/index.php/topic,5207.0.html
+
+ # Create a symlink to a file that is outside of the vroot
+ my $outside_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $outside_file")) {
print $fh "Hello, World!\n";
unless (close($fh)) {
- die("Can't write $src_file: $!");
+ die("Can't write $outside_file: $!");
}
} else {
- die("Can't open $src_file: $!");
+ die("Can't open $outside_file: $!");
}
- my $dst_file = '~/bar.txt';
+ my $cwd = getcwd();
+
+ unless (chdir($home_dir)) {
+ die("Can't chdir to $home_dir: $!");
+ }
+
+ unless (symlink("../foo.txt", "foo.lnk")) {
+ die("Can't symlink '../foo.txt' to 'foo.lnk': $!");
+ }
+
+ unless (chdir($cwd)) {
+ die("Can't chdir to $cwd: $!");
+ }
+
+ # Now create a symlink which points inside the vroot
+ my $inside_file = File::Spec->rel2abs("$tmpdir/home/bar.txt");
+ if (open(my $fh, "> $inside_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $inside_file: $!");
+ }
+
+ } else {
+ die("Can't open $inside_file: $!");
+ }
+
+ my $cwd = getcwd();
+
+ unless (chdir($home_dir)) {
+ die("Can't chdir to $home_dir: $!");
+ }
+
+ unless (symlink("./bar.txt", "bar.lnk")) {
+ die("Can't symlink './bar.txt' to 'bar.lnk': $!");
+ }
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ unless (chdir($cwd)) {
+ die("Can't chdir to $cwd: $!");
+ }
my $config = {
PidFile => $pid_file,
@@ -8719,20 +9459,16 @@ sub vroot_alias_file_sftp_write_no_overwrite {
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
- IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
+ # ShowSymlinks is on by default, but explicitly list it here for
+ # completeness
+ ShowSymlinks => 'on',
+ IfModules => {
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- DefaultRoot => '~',
- VRootAlias => "$src_file $dst_file",
+ DefaultRoot => $home_dir,
},
'mod_delay.c' => {
@@ -8751,50 +9487,73 @@ sub vroot_alias_file_sftp_write_no_overwrite {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# Fork child
$self->handle_sigchld();
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
- my $ssh2 = Net::SSH2->new();
-
- sleep(1);
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- 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");
+ my $conn = $client->list_raw();
+ unless ($conn) {
+ die("Failed to LIST: " . $client->response_code() . " " .
+ $client->response_msg());
}
- unless ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $buf;
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ # 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->{$1} = 1;
+ }
}
- my $fh = $sftp->open('bar.txt', O_WRONLY|O_TRUNC, 0644);
- if ($fh) {
- die("OPEN bar.txt succeeded unexpectedly");
+ unless (scalar(keys(%$res)) > 0) {
+ die("LIST data unexpectedly empty");
+ }
+
+ my $expected = {
+ 'bar.txt' => 1,
+ };
+
+ my $ok = 1;
+ my $mismatch;
+ foreach my $name (keys(%$res)) {
+ unless (defined($expected->{$name})) {
+ $mismatch = $name;
+ $ok = 0;
+ last;
+ }
}
- my ($err_code, $err_name) = $sftp->error();
+ unless ($ok) {
+ die("Unexpected name '$mismatch' appeared in LIST data")
+ }
+
+ # Try to download from the symlink
+ my $conn = $client->retr_raw('bar.txt');
+ unless ($conn) {
+ die("RETR bar.txt failed: " . $client->response_code() . " " .
+ $client->response_msg());
+ }
+
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
- my $expected = 'SSH_FX_PERMISSION_DENIED';
- $self->assert($expected eq $err_name,
- test_msg("Expected '$expected', got '$err_name'"));
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -8806,7 +9565,8 @@ sub vroot_alias_file_sftp_write_no_overwrite {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -8819,13 +9579,16 @@ sub vroot_alias_file_sftp_write_no_overwrite {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_file_sftp_write {
+sub vroot_hiddenstores_on_double_dot {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -8833,7 +9596,7 @@ sub vroot_alias_file_sftp_write {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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");
@@ -8860,22 +9623,6 @@ sub vroot_alias_file_sftp_write {
'/bin/bash');
auth_group_write($auth_group_file, 'ftpd', $gid, $user);
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $src_file: $!");
- }
-
- } else {
- die("Can't open $src_file: $!");
- }
-
- my $dst_file = '~/bar.txt';
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
-
my $config = {
PidFile => $pid_file,
ScoreboardFile => $scoreboard_file,
@@ -8887,21 +9634,14 @@ sub vroot_alias_file_sftp_write {
AuthGroupFile => $auth_group_file,
AllowOverwrite => 'on',
+ HiddenStores => 'on',
IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
-
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- DefaultRoot => '~',
- VRootAlias => "$src_file $dst_file",
+ DefaultRoot => '~',
},
'mod_delay.c' => {
@@ -8920,53 +9660,32 @@ sub vroot_alias_file_sftp_write {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# 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($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
-
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- my $fh = $sftp->open('bar.txt', O_WRONLY|O_TRUNC, 0644);
- unless ($fh) {
- my ($err_code, $err_name) = $sftp->error();
- die("Can't open bar.txt: [$err_name] ($err_code)");
+ # Try to upload a file whose name starts with a period
+ my $conn = $client->stor_raw('.foo');
+ unless ($conn) {
+ die("STOR .foo failed: " . $client->response_code() . ' ' .
+ $client->response_msg());
}
- my $count = 20;
- for (my $i = 0; $i < $count; $i++) {
- print $fh "ABCD" x 4096;
- }
+ my $buf = "Farewell, cruel world";
+ $conn->write($buf, length($buf), 25);
+ eval { $conn->close() };
- # To issue the FXP_CLOSE, we have to explicit destroy the filehandle
- $fh = undef;
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -8991,13 +9710,16 @@ sub vroot_alias_file_sftp_write {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_file_sftp_stat {
+sub vroot_mfmt {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -9005,17 +9727,29 @@ sub vroot_alias_file_sftp_stat {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
+ my $test_file = File::Spec->rel2abs("$tmpdir/test.txt");
+ if (open(my $fh, "> $test_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $test_file: $!");
+ }
+
+ } 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) {
@@ -9030,48 +9764,23 @@ sub vroot_alias_file_sftp_stat {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $src_file: $!");
- }
-
- } else {
- die("Can't open $src_file: $!");
- }
-
- my $dst_file = '~/bar.txt';
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ 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:10',
+ Trace => 'fsio:10 vroot:20',
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
-
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
DefaultRoot => '~',
-
- VRootAlias => "$src_file $dst_file",
},
'mod_delay.c' => {
@@ -9090,60 +9799,74 @@ sub vroot_alias_file_sftp_stat {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# Fork child
$self->handle_sigchld();
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
- my $ssh2 = Net::SSH2->new();
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- sleep(1);
+ my ($resp_code, $resp_msg);
- 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");
- }
+ # First try MFMT using relative paths
+ my $path = './test.txt';
+ ($resp_code, $resp_msg) = $client->mfmt('20020717210715', $path);
- unless ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $expected;
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ $expected = 213;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "Modify=20020717210715; $path";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ $path = "test.txt";
+ ($resp_code, $resp_msg) = $client->mfmt('20020717210715', $path);
+
+ $expected = 213;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "Modify=20020717210715; $path";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
- my $attrs = $sftp->stat('bar.txt', 1);
- unless ($attrs) {
- my ($err_code, $err_name) = $sftp->error();
- die("FXP_STAT bar.txt failed: [$err_name] ($err_code)");
+ # Next try an absolute path (from client perspective)
+ $path = "/test.txt";
+ ($resp_code, $resp_msg) = $client->mfmt('20020717210715', $path);
+
+ $expected = 213;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
+
+ $expected = "Modify=20020717210715; $path";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
+
+ # Last try the real absolute path
+ $path = $test_file;
+ eval { $client->mfmt('20020717210715', $path) };
+ unless ($@) {
+ die("MFMT $path succeeded unexpectedly");
}
- my $expected = 14;
- my $file_size = $attrs->{size};
- $self->assert($expected == $file_size,
- test_msg("Expected $expected, got $file_size"));
+ $resp_code = $client->response_code();
+ $resp_msg = $client->response_msg();
- $expected = $<;
- my $file_uid = $attrs->{uid};
- $self->assert($expected == $file_uid,
- test_msg("Expected '$expected', got '$file_uid'"));
+ $expected = 550;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
- $expected = $(;
- my $file_gid = $attrs->{gid};
- $self->assert($expected == $file_gid,
- test_msg("Expected '$expected', got '$file_gid'"));
+ $expected = "$path: No such file or directory";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -9155,7 +9878,8 @@ sub vroot_alias_file_sftp_stat {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -9168,13 +9892,16 @@ sub vroot_alias_file_sftp_stat {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_file_sftp_lstat {
+sub vroot_log_extlog_retr {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -9182,13 +9909,14 @@ sub vroot_alias_file_sftp_lstat {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -9207,23 +9935,20 @@ sub vroot_alias_file_sftp_lstat {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
+ my $test_file = File::Spec->rel2abs("$tmpdir/test.txt");
+ if (open(my $fh, "> $test_file")) {
print $fh "Hello, World!\n";
unless (close($fh)) {
- die("Can't write $src_file: $!");
+ die("Can't write $test_file: $!");
}
} else {
- die("Can't open $src_file: $!");
+ die("Can't open $test_file: $!");
}
- my $dst_file = '~/bar.txt';
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ my $ext_log = File::Spec->rel2abs("$tmpdir/custom.log");
my $config = {
PidFile => $pid_file,
@@ -9235,20 +9960,15 @@ sub vroot_alias_file_sftp_lstat {
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
- IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
+ LogFormat => 'custom "%f"',
+ ExtendedLog => "$ext_log READ custom",
+ IfModules => {
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- DefaultRoot => '~',
- VRootAlias => "$src_file $dst_file",
+ DefaultRoot => '~',
},
'mod_delay.c' => {
@@ -9267,60 +9987,31 @@ sub vroot_alias_file_sftp_lstat {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# 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($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
-
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- my $attrs = $sftp->stat('bar.txt', 0);
- unless ($attrs) {
- my ($err_code, $err_name) = $sftp->error();
- die("FXP_STAT bar.txt failed: [$err_name] ($err_code)");
+ my $conn = $client->retr_raw('test.txt');
+ unless ($conn) {
+ die("Failed to RETR test.txt: " . $client->response_code() . " " .
+ $client->response_msg());
}
- my $expected = 14;
- my $file_size = $attrs->{size};
- $self->assert($expected == $file_size,
- test_msg("Expected $expected, got $file_size"));
-
- $expected = $<;
- my $file_uid = $attrs->{uid};
- $self->assert($expected == $file_uid,
- test_msg("Expected '$expected', got '$file_uid'"));
+ my $buf;
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
- $expected = $(;
- my $file_gid = $attrs->{gid};
- $self->assert($expected == $file_gid,
- test_msg("Expected '$expected', got '$file_gid'"));
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -9332,7 +10023,8 @@ sub vroot_alias_file_sftp_lstat {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -9344,14 +10036,36 @@ sub vroot_alias_file_sftp_lstat {
$self->assert_child_ok($pid);
+ # Now, read in the ExtendedLog, and see whether the %f variable was
+ # properly written out.
+ if (open(my $fh, "< $ext_log")) {
+ my $line = <$fh>;
+ chomp($line);
+ close($fh);
+
+ if ($^O eq 'darwin') {
+ # MacOSX-specific hack, due to how it handles tmp files
+ $test_file = ('/private' . $test_file);
+ }
+
+ $self->assert($test_file eq $line,
+ test_msg("Expected '$test_file', got '$line'"));
+
+ } else {
+ die("Can't read $ext_log: $!");
+ }
+
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_file_sftp_realpath {
+sub vroot_log_extlog_stor {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -9359,13 +10073,14 @@ sub vroot_alias_file_sftp_realpath {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -9384,23 +10099,11 @@ sub vroot_alias_file_sftp_realpath {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $src_file: $!");
- }
-
- } else {
- die("Can't open $src_file: $!");
- }
+ auth_group_write($auth_group_file, $group, $gid, $user);
- my $dst_file = '~/bar.txt';
+ my $test_file = File::Spec->rel2abs("$tmpdir/test.txt");
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ my $ext_log = File::Spec->rel2abs("$tmpdir/custom.log");
my $config = {
PidFile => $pid_file,
@@ -9412,20 +10115,15 @@ sub vroot_alias_file_sftp_realpath {
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
- IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
+ LogFormat => 'custom "%f"',
+ ExtendedLog => "$ext_log WRITE custom",
+ IfModules => {
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- DefaultRoot => '~',
- VRootAlias => "$src_file $dst_file",
+ DefaultRoot => '~',
},
'mod_delay.c' => {
@@ -9444,51 +10142,31 @@ sub vroot_alias_file_sftp_realpath {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# 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($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
-
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- my $real_path = $sftp->realpath('bar.txt');
- unless ($real_path) {
- my ($err_code, $err_name) = $sftp->error();
- die("Can't get real path for 'bar.txt': [$err_name] ($err_code)");
+ my $conn = $client->stor_raw('test.txt');
+ unless ($conn) {
+ die("Failed to STOR test.txt: " . $client->response_code() . " " .
+ $client->response_msg());
}
- my $expected;
+ my $buf = "Hello, World!";
+ $conn->write($buf, length($buf), 5);
+ eval { $conn->close() };
- $expected = '/bar.txt';
- $self->assert($expected eq $real_path,
- test_msg("Expected '$expected', got '$real_path'"));
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -9500,7 +10178,8 @@ sub vroot_alias_file_sftp_realpath {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -9512,14 +10191,36 @@ sub vroot_alias_file_sftp_realpath {
$self->assert_child_ok($pid);
- if ($ex) {
- die($ex);
- }
+ # Now, read in the ExtendedLog, and see whether the %f variable was
+ # properly written out.
+ if (open(my $fh, "< $ext_log")) {
+ my $line = <$fh>;
+ chomp($line);
+ close($fh);
+
+ if ($^O eq 'darwin') {
+ # MacOSX-specific hack, due to how it handles tmp files
+ $test_file = ('/private' . $test_file);
+ }
+
+ $self->assert($test_file eq $line,
+ test_msg("Expected '$test_file', got '$line'"));
+
+ } else {
+ die("Can't read $ext_log: $!");
+ }
+
+ if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
+ die($ex);
+ }
unlink($log_file);
}
-sub vroot_alias_file_sftp_remove {
+sub vroot_log_xferlog_retr {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -9527,13 +10228,14 @@ sub vroot_alias_file_sftp_remove {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -9552,23 +10254,20 @@ sub vroot_alias_file_sftp_remove {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
+ my $test_file = File::Spec->rel2abs("$tmpdir/test.txt");
+ if (open(my $fh, "> $test_file")) {
print $fh "Hello, World!\n";
unless (close($fh)) {
- die("Can't write $src_file: $!");
+ die("Can't write $test_file: $!");
}
} else {
- die("Can't open $src_file: $!");
+ die("Can't open $test_file: $!");
}
- my $dst_file = '~/bar.txt';
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ my $xfer_log = File::Spec->rel2abs("$tmpdir/xfer.log");
my $config = {
PidFile => $pid_file,
@@ -9580,20 +10279,14 @@ sub vroot_alias_file_sftp_remove {
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
- IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
+ TransferLog => $xfer_log,
+ IfModules => {
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- DefaultRoot => '~',
- VRootAlias => "$src_file $dst_file",
+ DefaultRoot => '~',
},
'mod_delay.c' => {
@@ -9612,50 +10305,32 @@ sub vroot_alias_file_sftp_remove {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# 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($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
-
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
+ $client->type('binary');
- my $res = $sftp->unlink('bar.txt');
- if ($res) {
- die("REMOVE bar.txt succeeded unexpectedly");
+ my $conn = $client->retr_raw('test.txt');
+ unless ($conn) {
+ die("Failed to RETR test.txt: " . $client->response_code() . " " .
+ $client->response_msg());
}
- my ($err_code, $err_name) = $sftp->error();
+ my $buf;
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
- my $expected = 'SSH_FX_PERMISSION_DENIED';
- $self->assert($expected eq $err_name,
- test_msg("Expected '$expected', got '$err_name'"));
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -9667,7 +10342,8 @@ sub vroot_alias_file_sftp_remove {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -9679,14 +10355,64 @@ sub vroot_alias_file_sftp_remove {
$self->assert_child_ok($pid);
+ if (open(my $fh, "< $xfer_log")) {
+ my $line = <$fh>;
+ chomp($line);
+ close($fh);
+
+ my $expected = '^\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+\s+\d+\s+(\S+)\s+(\d+)\s+(\S+)\s+(\S+)\s+_\s+o\s+r\s+(\S+)\s+ftp\s+0\s+\*\s+c$';
+
+ $self->assert(qr/$expected/, $line,
+ test_msg("Expected '$expected', got '$line'"));
+
+ if ($line =~ /$expected/) {
+ my $remote_host = $1;
+ my $filesz = $2;
+ my $filename = $3;
+ my $xfer_type = $4;
+ my $user_name = $5;
+
+ if ($^O eq 'darwin') {
+ # MacOSX-specific hack, due to how it handles tmp files
+ $test_file = ('/private' . $test_file);
+ }
+
+ $expected = '127.0.0.1';
+ $self->assert($expected eq $remote_host,
+ test_msg("Expected '$expected', got '$remote_host'"));
+
+ $expected = -s $test_file;
+ $self->assert($expected == $filesz,
+ test_msg("Expected '$expected', got '$filesz'"));
+
+ $expected = $test_file;
+ $self->assert($expected eq $filename,
+ test_msg("Expected '$expected', got '$filename'"));
+
+ $expected = 'b';
+ $self->assert($expected eq $xfer_type,
+ test_msg("Expected '$expected', got '$xfer_type'"));
+
+ $expected = $user;
+ $self->assert($expected eq $user_name,
+ test_msg("Expected '$expected', got '$user_name'"));
+ }
+
+ } else {
+ die("Can't read $xfer_log: $!");
+ }
+
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_dir_sftp_readdir {
+sub vroot_log_xferlog_stor {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -9694,13 +10420,14 @@ sub vroot_alias_dir_sftp_readdir {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -9719,39 +10446,11 @@ sub vroot_alias_dir_sftp_readdir {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
- mkpath($src_dir);
-
- my $dst_dir = '~/bar.d';
-
- my $test_file1 = File::Spec->rel2abs("$tmpdir/foo.d/a.txt");
- if (open(my $fh, "> $test_file1")) {
- close($fh);
-
- } else {
- die("Can't open $test_file1: $!");
- }
-
- my $test_file2 = File::Spec->rel2abs("$tmpdir/foo.d/b.txt");
- if (open(my $fh, "> $test_file2")) {
- close($fh);
-
- } else {
- die("Can't open $test_file2: $!");
- }
-
- my $test_file3 = File::Spec->rel2abs("$tmpdir/foo.d/c.txt");
- if (open(my $fh, "> $test_file3")) {
- close($fh);
+ auth_group_write($auth_group_file, $group, $gid, $user);
- } else {
- die("Can't open $test_file3: $!");
- }
+ my $test_file = File::Spec->rel2abs("$tmpdir/test.txt");
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ my $xfer_log = File::Spec->rel2abs("$tmpdir/xfer.log");
my $config = {
PidFile => $pid_file,
@@ -9763,20 +10462,14 @@ sub vroot_alias_dir_sftp_readdir {
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
- IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
+ TransferLog => $xfer_log,
+ IfModules => {
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- DefaultRoot => '~',
- VRootAlias => "$src_dir $dst_dir",
+ DefaultRoot => '~',
},
'mod_delay.c' => {
@@ -9795,92 +10488,32 @@ sub vroot_alias_dir_sftp_readdir {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# 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($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
-
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
-
- my $dir = $sftp->opendir('bar.d');
- unless ($dir) {
- my ($err_code, $err_name) = $sftp->error();
- die("Can't open directory 'bar.d': [$err_name] ($err_code)");
- }
-
- my $res = {};
-
- my $file = $dir->read();
- while ($file) {
- $res->{$file->{name}} = $file;
- $file = $dir->read();
- }
-
- my $expected = {
- '.' => 1,
- '..' => 1,
- 'a.txt' => 1,
- 'b.txt' => 1,
- 'c.txt' => 1,
- };
-
- # To issue the FXP_CLOSE, we have to explicit destroy the dirhandle
- $dir = undef;
-
- $ssh2->disconnect();
-
- my $ok = 1;
- my $mismatch;
-
- my $seen = [];
- foreach my $name (keys(%$res)) {
- push(@$seen, $name);
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
+ $client->type('binary');
- unless (defined($expected->{$name})) {
- $mismatch = $name;
- $ok = 0;
- last;
- }
+ my $conn = $client->stor_raw('test.txt');
+ unless ($conn) {
+ die("Failed to STOR test.txt: " . $client->response_code() . " " .
+ $client->response_msg());
}
- unless ($ok) {
- die("Unexpected name '$mismatch' appeared in READDIR data")
- }
+ my $buf = "Hello, World!";
+ $conn->write($buf, length($buf), 5);
+ eval { $conn->close() };
- # Now remove from $expected all of the paths we saw; if there are
- # any entries remaining in $expected, something went wrong.
- foreach my $name (@$seen) {
- delete($expected->{$name});
- }
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
- my $remaining = scalar(keys(%$expected));
- $self->assert(0 == $remaining,
- test_msg("Expected 0, got $remaining"));
+ $client->quit();
};
if ($@) {
@@ -9892,7 +10525,8 @@ sub vroot_alias_dir_sftp_readdir {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -9904,14 +10538,64 @@ sub vroot_alias_dir_sftp_readdir {
$self->assert_child_ok($pid);
+ if (open(my $fh, "< $xfer_log")) {
+ my $line = <$fh>;
+ chomp($line);
+ close($fh);
+
+ my $expected = '^\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+\s+\d+\s+(\S+)\s+(\d+)\s+(\S+)\s+(\S+)\s+_\s+i\s+r\s+(\S+)\s+ftp\s+0\s+\*\s+c$';
+
+ $self->assert(qr/$expected/, $line,
+ test_msg("Expected '$expected', got '$line'"));
+
+ if ($line =~ /$expected/) {
+ my $remote_host = $1;
+ my $filesz = $2;
+ my $filename = $3;
+ my $xfer_type = $4;
+ my $user_name = $5;
+
+ if ($^O eq 'darwin') {
+ # MacOSX-specific hack, due to how it handles tmp files
+ $test_file = ('/private' . $test_file);
+ }
+
+ $expected = '127.0.0.1';
+ $self->assert($expected eq $remote_host,
+ test_msg("Expected '$expected', got '$remote_host'"));
+
+ $expected = -s $test_file;
+ $self->assert($expected == $filesz,
+ test_msg("Expected '$expected', got '$filesz'"));
+
+ $expected = $test_file;
+ $self->assert($expected eq $filename,
+ test_msg("Expected '$expected', got '$filename'"));
+
+ $expected = 'b';
+ $self->assert($expected eq $xfer_type,
+ test_msg("Expected '$expected', got '$xfer_type'"));
+
+ $expected = $user;
+ $self->assert($expected eq $user_name,
+ test_msg("Expected '$expected', got '$user_name'"));
+ }
+
+ } else {
+ die("Can't read $xfer_log: $!");
+ }
+
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_dir_sftp_rmdir {
+sub vroot_config_limit_write {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -9919,13 +10603,14 @@ sub vroot_alias_dir_sftp_rmdir {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -9944,40 +10629,24 @@ sub vroot_alias_dir_sftp_rmdir {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
- mkpath($src_dir);
-
- my $dst_dir = '~/bar.d';
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ 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:10',
+ Trace => 'directory:20 fsio:10',
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
-
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- DefaultRoot => '~',
- VRootAlias => "$src_dir $dst_dir",
+ DefaultRoot => '~',
},
'mod_delay.c' => {
@@ -9988,6 +10657,22 @@ sub vroot_alias_dir_sftp_rmdir {
my ($port, $config_user, $config_group) = config_write($config_file, $config);
+ if (open(my $fh, ">> $config_file")) {
+ print $fh <<EOC;
+<Directory $home_dir>
+ <Limit WRITE>
+ DenyAll
+ </Limit>
+</Directory>
+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.
@@ -9996,50 +10681,36 @@ sub vroot_alias_dir_sftp_rmdir {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# 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");
- }
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- unless ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ my $conn = $client->stor_raw('test.txt');
+ if ($conn) {
+ eval { $conn->close() };
+ die("STOR test.txt succeeded unexpectedly");
}
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
- my $res = $sftp->rmdir('/bar.d');
- if ($res) {
- die("RMDIR bar.d succeeded unexpectedly");
- }
+ my $expected;
- my ($err_code, $err_name) = $sftp->error();
+ $expected = 550;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
- my $expected = 'SSH_FX_PERMISSION_DENIED';
- $self->assert($expected eq $err_name,
- test_msg("Expected '$expected', got '$err_name'"));
+ $expected = "test.txt: Permission denied";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -10051,7 +10722,8 @@ sub vroot_alias_dir_sftp_rmdir {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -10064,13 +10736,16 @@ sub vroot_alias_dir_sftp_rmdir {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_symlink_sftp_stat {
+sub vroot_config_deleteabortedstores_conn_aborted {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -10078,13 +10753,14 @@ sub vroot_alias_symlink_sftp_stat {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -10103,64 +10779,30 @@ sub vroot_alias_symlink_sftp_stat {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $src_file: $!");
- }
+ auth_group_write($auth_group_file, $group, $gid, $user);
- } else {
- die("Can't open $src_file: $!");
- }
+ my $hidden_file = File::Spec->rel2abs("$tmpdir/.in.test.txt.");
+ my $test_file = File::Spec->rel2abs("$tmpdir/test.txt");
- my $cwd = getcwd();
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10 vroot:20',
- unless (chdir($home_dir)) {
- die("Can't chdir to $home_dir: $!");
- }
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
- unless (symlink("./foo.txt", "foo.lnk")) {
- die("Can't symlink './foo.txt' to 'foo.lnk': $!");
- }
-
- unless (chdir($cwd)) {
- die("Can't chdir to $cwd: $!");
- }
-
- my $src_symlink = File::Spec->rel2abs("$tmpdir/foo.lnk");
- my $dst_file = '~/bar.lnk';
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
-
- my $config = {
- PidFile => $pid_file,
- ScoreboardFile => $scoreboard_file,
- SystemLog => $log_file,
- TraceLog => $log_file,
- Trace => 'fsio:10',
-
- AuthUserFile => $auth_user_file,
- AuthGroupFile => $auth_group_file,
+ HiddenStores => 'on',
+ DeleteAbortedStores => 'on',
IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
-
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- VRootOptions => 'allowSymlinks',
- DefaultRoot => '~',
- VRootAlias => "$src_symlink $dst_file",
+ DefaultRoot => '~',
},
'mod_delay.c' => {
@@ -10179,60 +10821,42 @@ sub vroot_alias_symlink_sftp_stat {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# 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");
- }
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- unless ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ my $conn = $client->stor_raw('test.txt');
+ unless ($conn) {
+ die("Failed to STOR test.txt: " . $client->response_code() . ' ' .
+ $client->response_msg());
}
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $buf = "Hello, World!";
+ $conn->write($buf, length($buf), 5);
- my $attrs = $sftp->stat('bar.lnk', 1);
- unless ($attrs) {
- my ($err_code, $err_name) = $sftp->error();
- die("FXP_STAT bar.txt failed: [$err_name] ($err_code)");
+ unless (-f $hidden_file) {
+ die("File $hidden_file does not exist as expected");
}
- my $expected = 14;
- my $file_size = $attrs->{size};
- $self->assert($expected == $file_size,
- test_msg("Expected $expected, got $file_size"));
+ eval { $conn->abort() };
- $expected = $<;
- my $file_uid = $attrs->{uid};
- $self->assert($expected == $file_uid,
- test_msg("Expected '$expected', got '$file_uid'"));
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg, 1);
- $expected = $(;
- my $file_gid = $attrs->{gid};
- $self->assert($expected == $file_gid,
- test_msg("Expected '$expected', got '$file_gid'"));
+ if (-f $test_file) {
+ die("File $test_file exists unexpectedly");
+ }
- $ssh2->disconnect();
+ if (-f $hidden_file) {
+ die("File $hidden_file exists unexpectedly");
+ }
};
if ($@) {
@@ -10244,7 +10868,8 @@ sub vroot_alias_symlink_sftp_stat {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -10257,13 +10882,16 @@ sub vroot_alias_symlink_sftp_stat {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_symlink_sftp_lstat {
+sub vroot_config_deleteabortedstores_cmd_aborted {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -10271,13 +10899,14 @@ sub vroot_alias_symlink_sftp_lstat {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -10296,64 +10925,31 @@ sub vroot_alias_symlink_sftp_lstat {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $src_file: $!");
- }
-
- } else {
- die("Can't open $src_file: $!");
- }
-
- my $cwd = getcwd();
-
- unless (chdir($home_dir)) {
- die("Can't chdir to $home_dir: $!");
- }
-
- unless (symlink("./foo.txt", "foo.lnk")) {
- die("Can't symlink './foo.txt' to 'foo.lnk': $!");
- }
-
- unless (chdir($cwd)) {
- die("Can't chdir to $cwd: $!");
- }
-
- my $src_symlink = File::Spec->rel2abs("$tmpdir/foo.lnk");
- my $dst_file = '~/bar.lnk';
+ auth_group_write($auth_group_file, $group, $gid, $user);
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ my $hidden_file = File::Spec->rel2abs("$tmpdir/.in.test.txt.");
+ my $test_file = File::Spec->rel2abs("$tmpdir/test.txt");
my $config = {
PidFile => $pid_file,
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,
- IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
+ HiddenStores => 'on',
+ DeleteAbortedStores => 'on',
+ TimeoutLinger => 1,
+ IfModules => {
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- VRootOptions => 'allowSymlinks',
- DefaultRoot => '~',
- VRootAlias => "$src_symlink $dst_file",
+ DefaultRoot => '~',
},
'mod_delay.c' => {
@@ -10372,60 +10968,45 @@ sub vroot_alias_symlink_sftp_lstat {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# Fork child
$self->handle_sigchld();
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
- my $ssh2 = Net::SSH2->new();
-
- sleep(1);
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- 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");
+ my $conn = $client->stor_raw('test.txt');
+ unless ($conn) {
+ die("Failed to STOR test.txt: " . $client->response_code() . ' ' .
+ $client->response_msg());
}
- unless ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $buf = "Hello, World!";
+ $conn->write($buf, length($buf), 5);
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ unless (-f $hidden_file) {
+ die("File $hidden_file does not exist as expected");
}
- my $attrs = $sftp->stat('bar.lnk', 0);
- unless ($attrs) {
- my ($err_code, $err_name) = $sftp->error();
- die("FXP_STAT bar.txt failed: [$err_name] ($err_code)");
- }
+ $client->quote('ABOR');
- my $expected = 14;
- my $file_size = $attrs->{size};
- $self->assert($expected == $file_size,
- test_msg("Expected $expected, got $file_size"));
+ my $resp_code = $client->response_code();
+ my $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg, 1);
- $expected = $<;
- my $file_uid = $attrs->{uid};
- $self->assert($expected == $file_uid,
- test_msg("Expected '$expected', got '$file_uid'"));
+ eval { $conn->close() };
+ $client->quit();
- $expected = $(;
- my $file_gid = $attrs->{gid};
- $self->assert($expected == $file_gid,
- test_msg("Expected '$expected', got '$file_gid'"));
+ if (-f $test_file) {
+ die("File $test_file exists unexpectedly");
+ }
- $ssh2->disconnect();
+ if (-f $hidden_file) {
+ die("File $hidden_file exists unexpectedly");
+ }
};
if ($@) {
@@ -10437,7 +11018,8 @@ sub vroot_alias_symlink_sftp_lstat {
} else {
eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
+ if ($@) {
+ warn($@);
exit 1;
}
@@ -10450,13 +11032,16 @@ sub vroot_alias_symlink_sftp_lstat {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_symlink_sftp_realpath {
+sub vroot_alias_var_u_file {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -10464,13 +11049,14 @@ sub vroot_alias_symlink_sftp_realpath {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -10489,38 +11075,24 @@ sub vroot_alias_symlink_sftp_realpath {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
+ my $sub_dir = File::Spec->rel2abs("$tmpdir/$user");
+ mkpath($sub_dir);
+
+ my $src_path = File::Spec->rel2abs("$sub_dir/foo.txt");
+ if (open(my $fh, "> $src_path")) {
print $fh "Hello, World!\n";
unless (close($fh)) {
- die("Can't write $src_file: $!");
+ die("Can't write $src_path: $!");
}
} else {
- die("Can't open $src_file: $!");
- }
-
- my $cwd = getcwd();
-
- unless (chdir($home_dir)) {
- die("Can't chdir to $home_dir: $!");
- }
-
- unless (symlink("./foo.txt", "foo.lnk")) {
- die("Can't symlink './foo.txt' to 'foo.lnk': $!");
- }
-
- unless (chdir($cwd)) {
- die("Can't chdir to $cwd: $!");
+ die("Can't open $src_path: $!");
}
- my $src_symlink = File::Spec->rel2abs("$tmpdir/foo.lnk");
- my $dst_file = '~/bar.lnk';
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ my $src_file = File::Spec->rel2abs($tmpdir) . '/%u/foo.txt';
+ my $dst_file = '~/bar.txt';
my $config = {
PidFile => $pid_file,
@@ -10533,20 +11105,12 @@ sub vroot_alias_symlink_sftp_realpath {
AuthGroupFile => $auth_group_file,
IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
-
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
- VRootOptions => 'allowSymlinks',
DefaultRoot => '~',
- VRootAlias => "$src_symlink $dst_file",
+ VRootAlias => "$src_file $dst_file",
},
'mod_delay.c' => {
@@ -10565,49 +11129,84 @@ sub vroot_alias_symlink_sftp_realpath {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# Fork child
$self->handle_sigchld();
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
- my $ssh2 = Net::SSH2->new();
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- sleep(1);
+ my ($resp_code, $resp_msg);
+
+ ($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->list_raw();
+ unless ($conn) {
+ die("Failed to LIST: " . $client->response_code() . " " .
+ $client->response_msg());
+ }
+
+ my $buf;
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
- 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");
+ # 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 ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ unless (scalar(keys(%$res)) > 0) {
+ die("LIST data unexpectedly empty");
}
- my $sftp = $ssh2->sftp();
- unless ($sftp) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ $expected = {
+ 'vroot.conf' => 1,
+ 'vroot.group' => 1,
+ 'vroot.passwd' => 1,
+ 'vroot.pid' => 1,
+ 'vroot.scoreboard' => 1,
+ 'vroot.scoreboard.lck' => 1,
+ 'bar.txt' => 1,
+ 'proftpd' => 1,
+ };
+
+ my $ok = 1;
+ my $mismatch;
+ foreach my $name (keys(%$res)) {
+ unless (defined($expected->{$name})) {
+ $mismatch = $name;
+ $ok = 0;
+ last;
+ }
}
- my $real_path = $sftp->realpath('bar.lnk');
- unless ($real_path) {
- my ($err_code, $err_name) = $sftp->error();
- die("FXP_REALPATH bar.lnk failed: [$err_name] ($err_code)");
+ unless ($ok) {
+ die("Unexpected name '$mismatch' appeared in LIST data")
}
- my $expected = '/bar.lnk';
- $self->assert($expected eq $real_path,
- test_msg("Expected '$expected', got '$real_path'"));
+ my $mode = '-rw-r--r--';
+ $self->assert($mode eq $res->{'bar.txt'},
+ test_msg("Expected '$mode' for 'bar.txt', got '$res->{'bar.txt'}'"));
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -10632,13 +11231,16 @@ sub vroot_alias_symlink_sftp_realpath {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_alias_file_scp_download {
+sub vroot_alias_var_u_dir {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -10646,13 +11248,14 @@ sub vroot_alias_file_scp_download {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -10671,25 +11274,16 @@ sub vroot_alias_file_scp_download {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $src_file: $!");
- }
-
- } else {
- die("Can't open $src_file: $!");
- }
+ auth_group_write($auth_group_file, $group, $gid, $user);
- my $dst_file = '~/bar.txt';
+ my $sub_dir = File::Spec->rel2abs("$tmpdir/$user");
+ mkpath($sub_dir);
- my $test_file = File::Spec->rel2abs("tmpdir/test.txt");
+ my $src_path = File::Spec->rel2abs("$sub_dir/foo.d");
+ mkpath($src_path);
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+ my $src_file = File::Spec->rel2abs($tmpdir) . '/%u/foo.d';
+ my $dst_file = '~/bar.d';
my $config = {
PidFile => $pid_file,
@@ -10702,13 +11296,6 @@ sub vroot_alias_file_scp_download {
AuthGroupFile => $auth_group_file,
IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
-
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
@@ -10733,202 +11320,84 @@ sub vroot_alias_file_scp_download {
die("Can't open pipe: $!");
}
- require Net::SSH2;
-
my $ex;
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
# Fork child
$self->handle_sigchld();
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
- my $ssh2 = Net::SSH2->new();
+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+ $client->login($user, $passwd);
- sleep(1);
+ my ($resp_code, $resp_msg);
- 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");
- }
+ ($resp_code, $resp_msg) = $client->pwd();
- unless ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
- }
+ my $expected;
- my $res = $ssh2->scp_get('/bar.txt', $test_file);
- unless ($res) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't download bar.txt from server: [$err_name] ($err_code) $err_str");
- }
+ $expected = 257;
+ $self->assert($expected == $resp_code,
+ test_msg("Expected $expected, got $resp_code"));
- $ssh2->disconnect();
+ $expected = "\"/\" is the current directory";
+ $self->assert($expected eq $resp_msg,
+ test_msg("Expected '$expected', got '$resp_msg'"));
- unless (-f $test_file) {
- die("$test_file file does not exist as expected");
+ my $conn = $client->list_raw();
+ unless ($conn) {
+ die("Failed to LIST: " . $client->response_code() . " " .
+ $client->response_msg());
}
- };
-
- if ($@) {
- $ex = $@;
- }
- $wfh->print("done\n");
- $wfh->flush();
+ my $buf;
+ $conn->read($buf, 8192, 5);
+ eval { $conn->close() };
- } else {
- eval { server_wait($config_file, $rfh) };
- if ($@) { warn($@);
- exit 1;
- }
+ # 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;
+ }
+ }
- exit 0;
- }
-
- # Stop server
- server_stop($pid_file);
-
- $self->assert_child_ok($pid);
-
- if ($ex) {
- die($ex);
- }
-
- unlink($log_file);
-}
-
-sub vroot_alias_file_scp_upload {
- 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 = File::Spec->rel2abs('tests.log');
-
- 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 $home_dir = File::Spec->rel2abs($tmpdir);
- my $uid = 500;
- my $gid = 500;
-
- # 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: $!");
- }
-
- unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
-
- my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $src_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $src_file: $!");
- }
-
- } else {
- die("Can't open $src_file: $!");
- }
-
- my $dst_file = '~/bar.txt';
-
- my $test_file = File::Spec->rel2abs("tmpdir/test.txt");
-
- my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
- my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
-
- my $config = {
- PidFile => $pid_file,
- ScoreboardFile => $scoreboard_file,
- SystemLog => $log_file,
- TraceLog => $log_file,
- Trace => 'fsio:10',
-
- AuthUserFile => $auth_user_file,
- AuthGroupFile => $auth_group_file,
- AllowOverwrite => 'on',
-
- IfModules => {
- 'mod_sftp.c' => [
- "SFTPEngine on",
- "SFTPLog $log_file",
- "SFTPHostKey $rsa_host_key",
- "SFTPHostKey $dsa_host_key",
- ],
-
- 'mod_vroot.c' => {
- VRootEngine => 'on',
- VRootLog => $log_file,
- DefaultRoot => '~',
-
- VRootAlias => "$src_file $dst_file",
- },
-
- '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: $!");
- }
-
- require Net::SSH2;
-
- my $ex;
-
- # Ignore SIGPIPE
- local $SIG{PIPE} = sub { };
-
- # Fork child
- $self->handle_sigchld();
- defined(my $pid = fork()) or die("Can't fork: $!");
- if ($pid) {
- eval {
- my $ssh2 = Net::SSH2->new();
+ unless (scalar(keys(%$res)) > 0) {
+ die("LIST data unexpectedly empty");
+ }
- sleep(1);
+ $expected = {
+ 'vroot.conf' => 1,
+ 'vroot.group' => 1,
+ 'vroot.passwd' => 1,
+ 'vroot.pid' => 1,
+ 'vroot.scoreboard' => 1,
+ 'vroot.scoreboard.lck' => 1,
+ 'bar.d' => 1,
+ 'proftpd' => 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");
+ my $ok = 1;
+ my $mismatch;
+ foreach my $name (keys(%$res)) {
+ unless (defined($expected->{$name})) {
+ $mismatch = $name;
+ $ok = 0;
+ last;
+ }
}
- unless ($ssh2->auth_password($user, $passwd)) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ unless ($ok) {
+ die("Unexpected name '$mismatch' appeared in LIST data")
}
- my $res = $ssh2->scp_put($config_file, '/bar.txt');
- unless ($res) {
- my ($err_code, $err_name, $err_str) = $ssh2->error();
- die("Can't upload bar.txt to server: [$err_name] ($err_code) $err_str");
- }
+ my $mode = 'drwxr-xr-x';
+ $self->assert($mode eq $res->{'bar.d'},
+ test_msg("Expected '$mode' for 'bar.d', got '$res->{'bar.d'}'"));
- $ssh2->disconnect();
+ $client->quit();
};
if ($@) {
@@ -10953,13 +11422,16 @@ sub vroot_alias_file_scp_upload {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_showsymlinks_on {
+sub vroot_alias_var_u_dir_with_stor_mff {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -10967,19 +11439,18 @@ sub vroot_showsymlinks_on {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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 $home_dir = File::Spec->rel2abs("$tmpdir/home");
+ my $group = 'ftpd';
+ my $home_dir = File::Spec->rel2abs($tmpdir);
my $uid = 500;
my $gid = 500;
- mkpath($home_dir);
-
# Make sure that, if we're running as root, that the home directory has
# permissions/privs set for the account we create
if ($< == 0) {
@@ -10994,84 +11465,34 @@ sub vroot_showsymlinks_on {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- # See:
- #
- # http://forums.proftpd.org/smf/index.php/topic,5207.0.html
-
- # Create a symlink to a file that is outside of the vroot
- my $outside_file = File::Spec->rel2abs("$tmpdir/foo.txt");
- if (open(my $fh, "> $outside_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $outside_file: $!");
- }
-
- } else {
- die("Can't open $outside_file: $!");
- }
-
- my $cwd = getcwd();
-
- unless (chdir($home_dir)) {
- die("Can't chdir to $home_dir: $!");
- }
-
- unless (symlink("../foo.txt", "foo.lnk")) {
- die("Can't symlink '../foo.txt' to 'foo.lnk': $!");
- }
-
- unless (chdir($cwd)) {
- die("Can't chdir to $cwd: $!");
- }
-
- # Now create a symlink which points inside the vroot
- my $inside_file = File::Spec->rel2abs("$tmpdir/home/bar.txt");
- if (open(my $fh, "> $inside_file")) {
- print $fh "Hello, World!\n";
- unless (close($fh)) {
- die("Can't write $inside_file: $!");
- }
-
- } else {
- die("Can't open $inside_file: $!");
- }
-
- my $cwd = getcwd();
+ auth_group_write($auth_group_file, $group, $gid, $user);
- unless (chdir($home_dir)) {
- die("Can't chdir to $home_dir: $!");
- }
+ my $sub_dir = File::Spec->rel2abs("$tmpdir/sub.d");
+ mkpath($sub_dir);
- unless (symlink("./bar.txt", "bar.lnk")) {
- die("Can't symlink './bar.txt' to 'bar.lnk': $!");
- }
+ my $src_path = File::Spec->rel2abs("$sub_dir/foo.d");
+ mkpath($src_path);
- unless (chdir($cwd)) {
- die("Can't chdir to $cwd: $!");
- }
+ my $src_file = File::Spec->rel2abs($tmpdir) . '/sub.d/foo.d/';
+ my $dst_file = '/%u';
my $config = {
PidFile => $pid_file,
ScoreboardFile => $scoreboard_file,
SystemLog => $log_file,
TraceLog => $log_file,
- Trace => 'fsio:10',
+ Trace => 'DEFAULT:10 vroot:20 sql:10 fileperms:20',
AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
- # ShowSymlinks is on by default, but explicitly list it here for
- # completeness
- ShowSymlinks => 'on',
-
IfModules => {
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
+ DefaultRoot => '~',
- DefaultRoot => $home_dir,
+ VRootAlias => "$src_file $dst_file",
},
'mod_delay.c' => {
@@ -11098,9 +11519,20 @@ sub vroot_showsymlinks_on {
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->list_raw();
unless ($conn) {
die("Failed to LIST: " . $client->response_code() . " " .
@@ -11108,16 +11540,21 @@ sub vroot_showsymlinks_on {
}
my $buf;
- $conn->read($buf, 8192, 30);
+ $conn->read($buf, 8192, 5);
eval { $conn->close() };
+ sleep(1);
+
+ $resp_code = $client->response_code();
+ $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
# 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->{$1} = 1;
+ if ($line =~ /^(\S+)\s+\d+\s+\S+\s+\S+\s+.*?\s+(\S+)$/) {
+ $res->{$2} = $1;
}
}
@@ -11125,8 +11562,15 @@ sub vroot_showsymlinks_on {
die("LIST data unexpectedly empty");
}
- my $expected = {
- 'bar.txt' => 1,
+ $expected = {
+ 'vroot.conf' => 1,
+ 'vroot.group' => 1,
+ 'vroot.passwd' => 1,
+ 'vroot.pid' => 1,
+ 'vroot.scoreboard' => 1,
+ 'vroot.scoreboard.lck' => 1,
+ 'sub.d' => 1,
+ 'proftpd' => 1,
};
my $ok = 1;
@@ -11143,26 +11587,40 @@ sub vroot_showsymlinks_on {
die("Unexpected name '$mismatch' appeared in LIST data")
}
- # Try to download from the symlink
- my $conn = $client->retr_raw('bar.txt');
+ my $mode = 'drwxr-xr-x';
+ $self->assert($mode eq $res->{'proftpd'},
+ test_msg("Expected '$mode' for 'proftpd', got '$res->{'proftpd'}'"));
+
+ # Now change into the aliased directory, and upload a file there
+ ($resp_code, $resp_msg) = $client->cwd('proftpd');
+ sleep(1);
+
+ my $file = 'test.txt';
+ $conn = $client->stor_raw($file);
unless ($conn) {
- die("RETR bar.txt failed: " . $client->response_code() . " " .
+ die("STOR $file failed: " . $client->response_code() . " " .
$client->response_msg());
}
- $conn->read($buf, 8192, 30);
+ $buf = "Hello, World!\n";
+ $conn->write($buf, length($buf), 25);
eval { $conn->close() };
+ sleep(1);
- my $resp_code = $client->response_code();
- my $resp_msg = $client->response_msg();
+ $resp_code = $client->response_code();
+ $resp_msg = $client->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
- $expected = 226;
+ my $facts = 'Modify=20020717210715;Create=20120807064710';
+ ($resp_code, $resp_msg) = $client->mff($facts, $file);
+
+ $expected = 213;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ test_msg("Expected response code $expected, got $resp_code"));
- $expected = "Transfer complete";
+ $expected = "$facts $file";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ test_msg("Expected response message '$expected', got '$resp_msg'"));
$client->quit();
};
@@ -11175,9 +11633,8 @@ sub vroot_showsymlinks_on {
$wfh->flush();
} else {
- eval { server_wait($config_file, $rfh) };
- if ($@) {
- warn($@);
+ eval { server_wait($config_file, $rfh, 45) };
+ if ($@) { warn($@);
exit 1;
}
@@ -11190,13 +11647,16 @@ sub vroot_showsymlinks_on {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
unlink($log_file);
}
-sub vroot_hiddenstores_on_double_dot {
+sub vroot_alias_var_u_symlink_dir {
my $self = shift;
my $tmpdir = $self->{tmpdir};
@@ -11204,13 +11664,14 @@ sub vroot_hiddenstores_on_double_dot {
my $pid_file = File::Spec->rel2abs("$tmpdir/vroot.pid");
my $scoreboard_file = File::Spec->rel2abs("$tmpdir/vroot.scoreboard");
- my $log_file = File::Spec->rel2abs('tests.log');
+ 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);
my $uid = 500;
my $gid = 500;
@@ -11229,27 +11690,49 @@ sub vroot_hiddenstores_on_double_dot {
auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
'/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
+ auth_group_write($auth_group_file, $group, $gid, $user);
+
+ my $sub_dir = File::Spec->rel2abs("$tmpdir/$user");
+ mkpath($sub_dir);
+
+ my $src_path = File::Spec->rel2abs("$sub_dir/foo.d");
+ mkpath($src_path);
+
+ my $cwd = getcwd();
+
+ unless (chdir($sub_dir)) {
+ die("Can't chdir to $sub_dir: $!");
+ }
+
+ unless (symlink('foo.d', "./foo.lnk")) {
+ die("Can't symlink 'foo.d' to './foo.lnk': $!");
+ }
+
+ unless (chdir($cwd)) {
+ die("Can't chdir to $cwd: $!");
+ }
+
+ my $src_file = File::Spec->rel2abs($tmpdir) . '/%u/foo.lnk';
+ my $dst_file = '/%u.lnk';
my $config = {
PidFile => $pid_file,
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,
-
- AllowOverwrite => 'on',
- HiddenStores => 'on',
+ ShowSymlinks => 'off',
IfModules => {
'mod_vroot.c' => {
VRootEngine => 'on',
VRootLog => $log_file,
-
DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
},
'mod_delay.c' => {
@@ -11278,28 +11761,73 @@ sub vroot_hiddenstores_on_double_dot {
my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
$client->login($user, $passwd);
- # Try to upload a file whose name starts with a period
- my $conn = $client->stor_raw('.foo');
- unless ($conn) {
- die("STOR .foo failed: " . $client->response_code() . ' ' .
- $client->response_msg());
- }
+ my ($resp_code, $resp_msg);
- my $buf = "Farewell, cruel world";
- $conn->write($buf, length($buf), 30);
- eval { $conn->close() };
+ ($resp_code, $resp_msg) = $client->pwd();
- my $resp_code = $client->response_code();
- my $resp_msg = $client->response_msg();
+ my $expected;
- my $expected = 226;
+ $expected = 257;
$self->assert($expected == $resp_code,
test_msg("Expected $expected, got $resp_code"));
- $expected = 'Transfer complete';
+ $expected = "\"/\" is the current directory";
$self->assert($expected eq $resp_msg,
test_msg("Expected '$expected', got '$resp_msg'"));
+ 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.conf' => 1,
+ 'vroot.group' => 1,
+ 'vroot.passwd' => 1,
+ 'vroot.pid' => 1,
+ 'vroot.scoreboard' => 1,
+ 'vroot.scoreboard.lck' => 1,
+ 'proftpd.lnk' => 1,
+ 'proftpd' => 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->{'proftpd.lnk'},
+ test_msg("Expected '$mode' for 'proftpd.lnk', got '$res->{'proftpd.lnk'}'"));
+
$client->quit();
};
@@ -11325,6 +11853,9 @@ sub vroot_hiddenstores_on_double_dot {
$self->assert_child_ok($pid);
if ($ex) {
+ test_append_logfile($log_file, $ex);
+ unlink($log_file);
+
die($ex);
}
diff --git a/t/lib/ProFTPD/Tests/Modules/mod_vroot/sftp.pm b/t/lib/ProFTPD/Tests/Modules/mod_vroot/sftp.pm
new file mode 100644
index 0000000..18086aa
--- /dev/null
+++ b/t/lib/ProFTPD/Tests/Modules/mod_vroot/sftp.pm
@@ -0,0 +1,2603 @@
+package ProFTPD::Tests::Modules::mod_vroot::sftp;
+
+use lib qw(t/lib);
+use base qw(ProFTPD::TestSuite::Child);
+use strict;
+
+use Cwd;
+use Digest::MD5;
+use File::Path qw(mkpath rmtree);
+use File::Spec;
+use IO::Handle;
+use POSIX qw(:fcntl_h);
+
+use ProFTPD::TestSuite::FTP;
+use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite);
+
+$| = 1;
+
+my $order = 0;
+
+my $TESTS = {
+ vroot_alias_file_sftp_read => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_file_sftp_write_no_overwrite => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_file_sftp_write => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_file_sftp_stat => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_file_sftp_lstat => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_file_sftp_realpath => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_file_sftp_remove => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_dir_sftp_readdir => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_dir_sftp_rmdir => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_symlink_sftp_stat => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_symlink_sftp_lstat => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_symlink_sftp_realpath => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp sftp)],
+ },
+
+ vroot_alias_file_scp_download => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp scp)],
+ },
+
+ vroot_alias_file_scp_upload => {
+ order => ++$order,
+ test_class => [qw(forking mod_sftp scp)],
+ },
+
+};
+
+sub new {
+ return shift()->SUPER::new(@_);
+}
+
+sub list_tests {
+ return testsuite_get_runnable_tests($TESTS);
+
+# XXX test file aliases where the alias includes directories which do not
+# exist. Should we allow traversal of these kinds of aliases (if so, what
+# real directory do we use for perms, ownership? What would a CWD into
+# such a path component mean?), or only allow retrieval/storage to that
+# alias but not traversal?
+}
+
+sub set_up {
+ my $self = shift;
+ $self->SUPER::set_up(@_);
+
+ # Make sure that mod_sftp does not complain about permissions on the hostkey
+ # files.
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ unless (chmod(0400, $rsa_host_key, $dsa_host_key)) {
+ die("Can't set perms on $rsa_host_key, $dsa_host_key: $!");
+ }
+}
+
+sub vroot_alias_file_sftp_read {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $fh = $sftp->open('bar.txt', O_RDONLY);
+ unless ($fh) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("Can't open bar.txt: [$err_name] ($err_code)");
+ }
+
+ my $buf;
+ my $size = 0;
+
+ my $res = $fh->read($buf, 8192, 30);
+ while ($res) {
+ $size += $res;
+
+ $res = $fh->read($buf, 8192, 30);
+ }
+
+ # To issue the FXP_CLOSE, we have to explicit destroy the filehandle
+ $fh = undef;
+
+ my $expected = 14;
+ $self->assert($expected == $size,
+ test_msg("Expected $expected, got $size"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_file_sftp_write_no_overwrite {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $fh = $sftp->open('bar.txt', O_WRONLY|O_TRUNC, 0644);
+ if ($fh) {
+ die("OPEN bar.txt succeeded unexpectedly");
+ }
+
+ my ($err_code, $err_name) = $sftp->error();
+
+ my $expected = 'SSH_FX_PERMISSION_DENIED';
+ $self->assert($expected eq $err_name,
+ test_msg("Expected '$expected', got '$err_name'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_file_sftp_write {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ AllowOverwrite => 'on',
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $fh = $sftp->open('bar.txt', O_WRONLY|O_TRUNC, 0644);
+ unless ($fh) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("Can't open bar.txt: [$err_name] ($err_code)");
+ }
+
+ my $count = 20;
+ for (my $i = 0; $i < $count; $i++) {
+ print $fh "ABCD" x 4096;
+ }
+
+ # To issue the FXP_CLOSE, we have to explicit destroy the filehandle
+ $fh = undef;
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_file_sftp_stat {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $attrs = $sftp->stat('bar.txt', 1);
+ unless ($attrs) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("FXP_STAT bar.txt failed: [$err_name] ($err_code)");
+ }
+
+ my $expected = 14;
+ my $file_size = $attrs->{size};
+ $self->assert($expected == $file_size,
+ test_msg("Expected $expected, got $file_size"));
+
+ $expected = $<;
+ my $file_uid = $attrs->{uid};
+ $self->assert($expected == $file_uid,
+ test_msg("Expected '$expected', got '$file_uid'"));
+
+ $expected = $(;
+ my $file_gid = $attrs->{gid};
+ $self->assert($expected == $file_gid,
+ test_msg("Expected '$expected', got '$file_gid'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_file_sftp_lstat {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $attrs = $sftp->stat('bar.txt', 0);
+ unless ($attrs) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("FXP_STAT bar.txt failed: [$err_name] ($err_code)");
+ }
+
+ my $expected = 14;
+ my $file_size = $attrs->{size};
+ $self->assert($expected == $file_size,
+ test_msg("Expected $expected, got $file_size"));
+
+ $expected = $<;
+ my $file_uid = $attrs->{uid};
+ $self->assert($expected == $file_uid,
+ test_msg("Expected '$expected', got '$file_uid'"));
+
+ $expected = $(;
+ my $file_gid = $attrs->{gid};
+ $self->assert($expected == $file_gid,
+ test_msg("Expected '$expected', got '$file_gid'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_file_sftp_realpath {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $real_path = $sftp->realpath('bar.txt');
+ unless ($real_path) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("Can't get real path for 'bar.txt': [$err_name] ($err_code)");
+ }
+
+ my $expected;
+
+ $expected = '/bar.txt';
+ $self->assert($expected eq $real_path,
+ test_msg("Expected '$expected', got '$real_path'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_file_sftp_remove {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $res = $sftp->unlink('bar.txt');
+ if ($res) {
+ die("REMOVE bar.txt succeeded unexpectedly");
+ }
+
+ my ($err_code, $err_name) = $sftp->error();
+
+ my $expected = 'SSH_FX_PERMISSION_DENIED';
+ $self->assert($expected eq $err_name,
+ test_msg("Expected '$expected', got '$err_name'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_dir_sftp_readdir {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
+ mkpath($src_dir);
+
+ my $dst_dir = '~/bar.d';
+
+ my $test_file1 = File::Spec->rel2abs("$tmpdir/foo.d/a.txt");
+ if (open(my $fh, "> $test_file1")) {
+ close($fh);
+
+ } else {
+ die("Can't open $test_file1: $!");
+ }
+
+ my $test_file2 = File::Spec->rel2abs("$tmpdir/foo.d/b.txt");
+ if (open(my $fh, "> $test_file2")) {
+ close($fh);
+
+ } else {
+ die("Can't open $test_file2: $!");
+ }
+
+ my $test_file3 = File::Spec->rel2abs("$tmpdir/foo.d/c.txt");
+ if (open(my $fh, "> $test_file3")) {
+ close($fh);
+
+ } else {
+ die("Can't open $test_file3: $!");
+ }
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_dir $dst_dir",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $dir = $sftp->opendir('bar.d');
+ unless ($dir) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("Can't open directory 'bar.d': [$err_name] ($err_code)");
+ }
+
+ my $res = {};
+
+ my $file = $dir->read();
+ while ($file) {
+ $res->{$file->{name}} = $file;
+ $file = $dir->read();
+ }
+
+ my $expected = {
+ '.' => 1,
+ '..' => 1,
+ 'a.txt' => 1,
+ 'b.txt' => 1,
+ 'c.txt' => 1,
+ };
+
+ # To issue the FXP_CLOSE, we have to explicit destroy the dirhandle
+ $dir = undef;
+
+ $ssh2->disconnect();
+
+ my $ok = 1;
+ my $mismatch;
+
+ my $seen = [];
+ foreach my $name (keys(%$res)) {
+ push(@$seen, $name);
+
+ unless (defined($expected->{$name})) {
+ $mismatch = $name;
+ $ok = 0;
+ last;
+ }
+ }
+
+ unless ($ok) {
+ die("Unexpected name '$mismatch' appeared in READDIR data")
+ }
+
+ # Now remove from $expected all of the paths we saw; if there are
+ # any entries remaining in $expected, something went wrong.
+ foreach my $name (@$seen) {
+ delete($expected->{$name});
+ }
+
+ my $remaining = scalar(keys(%$expected));
+ $self->assert(0 == $remaining,
+ test_msg("Expected 0, got $remaining"));
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_dir_sftp_rmdir {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_dir = File::Spec->rel2abs("$tmpdir/foo.d");
+ mkpath($src_dir);
+
+ my $dst_dir = '~/bar.d';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_dir $dst_dir",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $res = $sftp->rmdir('/bar.d');
+ if ($res) {
+ die("RMDIR bar.d succeeded unexpectedly");
+ }
+
+ my ($err_code, $err_name) = $sftp->error();
+
+ my $expected = 'SSH_FX_PERMISSION_DENIED';
+ $self->assert($expected eq $err_name,
+ test_msg("Expected '$expected', got '$err_name'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_symlink_sftp_stat {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $cwd = getcwd();
+
+ unless (chdir($home_dir)) {
+ die("Can't chdir to $home_dir: $!");
+ }
+
+ unless (symlink("./foo.txt", "foo.lnk")) {
+ die("Can't symlink './foo.txt' to 'foo.lnk': $!");
+ }
+
+ unless (chdir($cwd)) {
+ die("Can't chdir to $cwd: $!");
+ }
+
+ my $src_symlink = File::Spec->rel2abs("$tmpdir/foo.lnk");
+ my $dst_file = '~/bar.lnk';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ VRootOptions => 'allowSymlinks',
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_symlink $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $attrs = $sftp->stat('bar.lnk', 1);
+ unless ($attrs) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("FXP_STAT bar.txt failed: [$err_name] ($err_code)");
+ }
+
+ my $expected = 14;
+ my $file_size = $attrs->{size};
+ $self->assert($expected == $file_size,
+ test_msg("Expected $expected, got $file_size"));
+
+ $expected = $<;
+ my $file_uid = $attrs->{uid};
+ $self->assert($expected == $file_uid,
+ test_msg("Expected '$expected', got '$file_uid'"));
+
+ $expected = $(;
+ my $file_gid = $attrs->{gid};
+ $self->assert($expected == $file_gid,
+ test_msg("Expected '$expected', got '$file_gid'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_symlink_sftp_lstat {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $cwd = getcwd();
+
+ unless (chdir($home_dir)) {
+ die("Can't chdir to $home_dir: $!");
+ }
+
+ unless (symlink("./foo.txt", "foo.lnk")) {
+ die("Can't symlink './foo.txt' to 'foo.lnk': $!");
+ }
+
+ unless (chdir($cwd)) {
+ die("Can't chdir to $cwd: $!");
+ }
+
+ my $src_symlink = File::Spec->rel2abs("$tmpdir/foo.lnk");
+ my $dst_file = '~/bar.lnk';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ VRootOptions => 'allowSymlinks',
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_symlink $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $attrs = $sftp->stat('bar.lnk', 0);
+ unless ($attrs) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("FXP_STAT bar.txt failed: [$err_name] ($err_code)");
+ }
+
+ my $expected = 14;
+ my $file_size = $attrs->{size};
+ $self->assert($expected == $file_size,
+ test_msg("Expected $expected, got $file_size"));
+
+ $expected = $<;
+ my $file_uid = $attrs->{uid};
+ $self->assert($expected == $file_uid,
+ test_msg("Expected '$expected', got '$file_uid'"));
+
+ $expected = $(;
+ my $file_gid = $attrs->{gid};
+ $self->assert($expected == $file_gid,
+ test_msg("Expected '$expected', got '$file_gid'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_symlink_sftp_realpath {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $cwd = getcwd();
+
+ unless (chdir($home_dir)) {
+ die("Can't chdir to $home_dir: $!");
+ }
+
+ unless (symlink("./foo.txt", "foo.lnk")) {
+ die("Can't symlink './foo.txt' to 'foo.lnk': $!");
+ }
+
+ unless (chdir($cwd)) {
+ die("Can't chdir to $cwd: $!");
+ }
+
+ my $src_symlink = File::Spec->rel2abs("$tmpdir/foo.lnk");
+ my $dst_file = '~/bar.lnk';
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ VRootOptions => 'allowSymlinks',
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_symlink $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $sftp = $ssh2->sftp();
+ unless ($sftp) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $real_path = $sftp->realpath('bar.lnk');
+ unless ($real_path) {
+ my ($err_code, $err_name) = $sftp->error();
+ die("FXP_REALPATH bar.lnk failed: [$err_name] ($err_code)");
+ }
+
+ my $expected = '/bar.lnk';
+ $self->assert($expected eq $real_path,
+ test_msg("Expected '$expected', got '$real_path'"));
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_file_scp_download {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $test_file = File::Spec->rel2abs("tmpdir/test.txt");
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $res = $ssh2->scp_get('/bar.txt', $test_file);
+ unless ($res) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't download bar.txt from server: [$err_name] ($err_code) $err_str");
+ }
+
+ $ssh2->disconnect();
+
+ unless (-f $test_file) {
+ die("$test_file 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+sub vroot_alias_file_scp_upload {
+ 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 = File::Spec->rel2abs('tests.log');
+
+ 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 $home_dir = File::Spec->rel2abs($tmpdir);
+ my $uid = 500;
+ my $gid = 500;
+
+ # 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: $!");
+ }
+
+ unless (chown($uid, $gid, $home_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, 'ftpd', $gid, $user);
+
+ my $src_file = File::Spec->rel2abs("$tmpdir/foo.txt");
+ if (open(my $fh, "> $src_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $src_file: $!");
+ }
+
+ } else {
+ die("Can't open $src_file: $!");
+ }
+
+ my $dst_file = '~/bar.txt';
+
+ my $test_file = File::Spec->rel2abs("tmpdir/test.txt");
+
+ my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
+ my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
+
+ my $config = {
+ PidFile => $pid_file,
+ ScoreboardFile => $scoreboard_file,
+ SystemLog => $log_file,
+ TraceLog => $log_file,
+ Trace => 'fsio:10',
+
+ AuthUserFile => $auth_user_file,
+ AuthGroupFile => $auth_group_file,
+ AllowOverwrite => 'on',
+
+ IfModules => {
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $log_file",
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+ ],
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ VRootLog => $log_file,
+ DefaultRoot => '~',
+
+ VRootAlias => "$src_file $dst_file",
+ },
+
+ '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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Ignore SIGPIPE
+ local $SIG{PIPE} = sub { };
+
+ # 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($user, $passwd)) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str");
+ }
+
+ my $res = $ssh2->scp_put($config_file, '/bar.txt');
+ unless ($res) {
+ my ($err_code, $err_name, $err_str) = $ssh2->error();
+ die("Can't upload bar.txt to server: [$err_name] ($err_code) $err_str");
+ }
+
+ $ssh2->disconnect();
+ };
+
+ 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) {
+ die($ex);
+ }
+
+ unlink($log_file);
+}
+
+1;
diff --git a/t/modules/mod_vroot.t b/t/modules/mod_vroot/sftp.t
similarity index 70%
copy from t/modules/mod_vroot.t
copy to t/modules/mod_vroot/sftp.t
index ce6599d..3c8cc91 100644
--- a/t/modules/mod_vroot.t
+++ b/t/modules/mod_vroot/sftp.t
@@ -8,4 +8,4 @@ use Test::Unit::HarnessUnit;
$| = 1;
my $r = Test::Unit::HarnessUnit->new();
-$r->start("ProFTPD::Tests::Modules::mod_vroot");
+$r->start("ProFTPD::Tests::Modules::mod_vroot::sftp");
--
proftpd module for mod_vroot
More information about the Pkg-proftpd-maintainers
mailing list